Why can't dataclasses have mutable defaults in their class attributes declaration?

场景还原

最近开发遇到一个问题是在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。这是一个部分解决方案,但它可以防止许多常见错误。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 一、Python简介和环境搭建以及pip的安装 4课时实验课主要内容 【Python简介】: Python 是一个...
    _小老虎_阅读 5,846评论 0 10
  • 这是16年5月份编辑的一份比较杂乱适合自己观看的学习记录文档,今天18年5月份再次想写文章,发现简书还为我保存起的...
    Jenaral阅读 2,869评论 2 9
  • ORA-00001: 违反唯一约束条件 (.) 错误说明:当在唯一索引所对应的列上键入重复值时,会触发此异常。 O...
    我想起个好名字阅读 5,453评论 0 9
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,148评论 1 32
  • 那会儿,天很蓝,云很白 青春,在记忆里,来过很多人 像是一卷发黄的胶片,有的地方已经记不清了 如果给别人讲记忆中排...
    张喜三阅读 91评论 0 0