12

Can anyone help me fix this error. I just started using dataclass I wanted to put a default value so I can easily call from other function

I have this class

@dataclass(frozen=True)
class MyClass:
    my_list: list = ["list1", "list2", "list3"]
    my_list2: list = ["list1", "list2", "list3"]

But when i print print(MyClass.my_list) I'm getting this error

 raise ValueError(f'mutable default {type(f.default)} for field '
ValueError: mutable default <class 'list'> for field my_list is not allowed: use default_factory
5
  • 2
    I know it's allowed, but it seems kind of anti-pattern to make a frozen dataclass with mutable objects. Are you sure this is what you want to do? Commented Oct 14, 2021 at 3:54
  • Ahm only i wanted is to put a default list values. Although I can use a dictionary for easy use but I'm currently learning dataclass and this helps me with typing hints Commented Oct 14, 2021 at 3:56
  • @sj95126 you mean I don't need to include frozen? since it's already mutable? How about if i wanted to put other data type? like str Commented Oct 14, 2021 at 4:03
  • 1
    Actually, removing frozen=True won't change the error, but all I meant is that as a general concept, a 'frozen' object with mutable contents is somewhat contradictory. There can be complications with hashing (see the documentation) so it may be better to avoid frozen in this case if you don't need it. Commented Oct 14, 2021 at 4:21
  • Yes thank you. I just removed it. Commented Oct 14, 2021 at 4:25

2 Answers 2

27

What it means by mutable default is that the lists provided as defaults will be the same individual objects in each instance of the dataclass. This would be confusing because mutating the list in an instance by e.g. appending to it would also append to the list in every other instance.

Instead, it wants you to provide a default_factory function that will make a new list for each instance:

from dataclasses import dataclass, field

@dataclass
class MyClass:
    my_list: list = field(default_factory=lambda: ["list1", "list2", "list3"])
    my_list2: list = field(default_factory=lambda: ["list1", "list2", "list3"])
Sign up to request clarification or add additional context in comments.

2 Comments

Thank you it fixed! At first I got error: AttributeError: type object 'MyClass' has no attribute 'my_list I forgot to include parenthesis. Now I get it. thank you so much
I need to wait for 5minutes to accept your answer
3

As the first comment notes, it's a bit odd to have a mutable item in a dataclass. If you don't need it to be mutable, a simpler solution is to initialize it as a tuple.

from dataclasses import dataclass

@dataclass
class MyClass:
    my_list: tuple[str] = ("list1", "list2", "list3")
    my_list2: tuple[str] = ("list1", "list2", "list3")

(For example, you might want a tuple of fieldnames associated with your dataclass for serialization with DictWriter.)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.