Gra*_*ham 15 python python-3.x
这似乎喜欢的事,很可能已被问过,但搜索的一个小时左右的时间没有结果。将默认列表参数传递给数据类看起来很有希望,但这并不是我想要的。
这是问题所在:当尝试将可变值分配给class属性时,会出现错误:
@dataclass
class Foo:
bar: list = []
# ValueError: mutable default <class 'list'> for field a is not allowed: use default_factory
Run Code Online (Sandbox Code Playgroud)
我从错误消息中收集了应该使用以下内容的信息:
@dataclass
class Foo:
bar: list = field(default_factory=list)
Run Code Online (Sandbox Code Playgroud)
但是为什么不允许可变的默认值?是否要强制避免可变的默认参数问题?
Shi*_*zzy 33
The above answer is not correct. A mutable default value, such as an empty list can be defined in data class by using default_factory.
@dataclass
class D:
x: list = field(default_factory=list)
Run Code Online (Sandbox Code Playgroud)
Using default factory functions is a way to create new instances of >mutable types as default values for fields:
Run Code Online (Sandbox Code Playgroud)@dataclass class D: x: list = field(default_factory=list) assert D().x is not D().x
The link is here
Met*_*orm 11
只需在 default_factory 中使用可调用的:
from dataclasses import dataclass, field
@dataclass
class SomeClass:
"""
"""
some_list: list = field(default_factory=lambda: ["your_values"])
Run Code Online (Sandbox Code Playgroud)
如果您希望所有实例都改变同一个列表:
from dataclasses import dataclass, field
SHARED_LIST = ["your_values"]
@dataclass
class SomeClass:
"""
"""
some_list: list = field(default_factory=lambda: SHARED_LIST)
Run Code Online (Sandbox Code Playgroud)
像数据类一样导入字段。
from dataclasses import dataclass, field
Run Code Online (Sandbox Code Playgroud)
并将其用于列表:
@dataclass
class Foo:
bar: list = field(default_factory=list)
Run Code Online (Sandbox Code Playgroud)
看来我的问题在docs中很清楚地得到了回答(如shmee所述,它源自PEP 557):
Python将默认的成员变量值存储在类属性中。考虑以下示例,不使用数据类:
Run Code Online (Sandbox Code Playgroud)class C: x = [] def add(self, element): self.x.append(element) o1 = C() o2 = C() o1.add(1) o2.add(2) assert o1.x == [1, 2] assert o1.x is o2.x请注意,class的两个实例按预期
C共享相同的class变量x。如果此代码有效,则使用数据类:
Run Code Online (Sandbox Code Playgroud)@dataclass class D: x: List = [] def add(self, element): self.x += element它会生成类似于以下内容的代码:
Run Code Online (Sandbox Code Playgroud)class D: x = [] def __init__(self, x=x): self.x = x def add(self, element): self.x += element这与使用class的原始示例具有相同的问题
C。也就是说,创建类实例时D未指定值x的两个类实例将共享的相同副本x。因为数据类仅使用常规的Python类创建,所以它们也共享此行为。数据类没有检测这种情况的通用方法。相反,数据类将抛出一个TypeError,如果它检测类型的默认参数list,dict或set。这是部分解决方案,但确实可以防止许多常见错误。
我偶然发现了这个问题,因为我确实想要一个静态列表作为类变量。这可以使用注释来完成ClassVar:
from typing import ClassVar
@dataclass
class Foo:
bar: ClassVar[list[str]] = ['hello', 'world']
Run Code Online (Sandbox Code Playgroud)