python dataclasses定义默认值为可变类型(转)

原文:https://zhuanlan.zhihu.com/p/59658886

作者:没有50CM手臂

网站:知乎

 

场景还原

最近开发遇到一个问题是在python3.7dataclass中不能使用可变的默认值,错误如下:

@dataclass
class Foo:
    bar: list = []

# ValueError: mutable default <class 'list'> for field a is not allowed: use default_factory

收到这种错误之后,修改为如下即可:

from dataclasses import (
  dataclass,
  field
)
@dataclass
class Foo:
    bar: list = field(default_factory=list)

深层解读

看起来我的问题在文档中得到了很清楚的回答(来自PEP 557,正如shmee所提到的):
Python在类属性中存储默认成员变量值。考虑这个例子,不使用数据类:

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

请注意,类的两个实例按预期C共享相同的类变量x。

使用数据类,如果此代码有效:

@dataclass
class D:
    x: List = []
    def add(self, element):
        self.x += element

它会生成类似于的代码:

class D:
    x = []
    def __init__(self, x=x):
        self.x = x
    def add(self, element):
        self.x += element'

这与使用类的原始示例具有相同的问题C。也就是说,在创建类实例时D没有指定值x的两个类实例将共享相同的副本x。由于数据类只使用普通的Python类创建,因此它们也会共享此行为。数据类没有通用的方法来检测这种情况。相反,数据类将抛出一个TypeError,如果它检测类型的默认参数list,dict或set。这是一个部分解决方案,但它可以防止许多常见错误。

posted @ 2023-04-20 13:12  奋斗终生  Views(658)  Comments(0Edit  收藏  举报