Change list to immutable object

Question:

As you can see input data and output my_data is mutable objects, how can I make my_data immutable and still have the possibility to iterate on it? (basically same behavior) use another dataclass?

from dataclasses import dataclass

data = {'demo1': "description for demo 1", "demo2": 'description for demo 2'}

@dataclass(frozen=True)
class SomeDataclass:
    name: str
    description: str



class ParserClass:
    def __init__(self) -> None:
        self.my_data = []

    def parsing_method(self, demo_data) -> None:
        for data, description in demo_data.items():
            self.my_data.append(SomeDataclass(name=data, description=description))

test = ParserClass()
test.parsing_method(data)
for my_date in test.my_data:
    print(my_date.name, my_date.description)
Asked By: Chaban33

||

Answers:

If your parser is a class, you can turn any of its attributes into read only attributes with @property:

class ParserClass:
    def __init__(self) -> None:
        self._my_data = []

    @property
    def my_data(self):
        return self._my_data.copy()  # copy to pass a new list, not the one in the parser

    def parsing_method(self, demo_data) -> None:
        for data, description in demo_data.items():
            self._my_data.append(SomeDataclass(name=data, description=description))

NB. as list are mutable, we are using copy to keep the private _my_data read-only, the returned copy can be modified (e.g. inst.my_data.append(something)), but that will not be reflected on the original private _my_data.

Or with @match’s suggestion:

class ParserClass:
    
    def __init__(self) -> None:
        self._my_data = tuple()

    def parsing_method(self, demo_data) -> None:
        tmp_data = []
        for data, description in demo_data.items():
            tmp_data.append(SomeDataclass(name=data, description=description))
        self.my_data = tuple(tmp_data)
Answered By: ljmc

I suppose you can simply convert them to tuples by using tuple() function. Tuple is immutable and iterable.

Edit: Someone else suggested it in a reply to your question when I was typing this. But I’ll just leave it here

Answered By: nomans_