繁体   English   中英

如何仅获取具有数据类的实例属性,而不是 class 属性?

[英]How to get only instance attributes with dataclasses, not class attributes?

考虑:

from dataclasses import dataclass, field

@dataclass
class Example:
    a: int
    b: int = 2
    c: int = field(default=3)
    d: int = field(default_factory=lambda: 4)

令我惊讶的是, Example.bExample.c存在,而Example.aExample.d不存在(是的,我在这里谈论的是 class 属性,而不是实例属性):

try:
    print(Example.a)
except AttributeError as e:
    print(e)
    # AttributeError: type object 'Example' has no attribute 'a'

print(Example.b)
# 2

print(Example.c)
# 3

try:
    print(Example.d)
except AttributeError as e:
    print(e)
    # AttributeError: type object 'Example' has no attribute 'd'

我希望他们都给出一个错误。 我想要的是实例属性,而不是 class 属性。 有时 class 属性也存在的事实似乎是错误的大门。

显然,根据我上面学到的知识,我可以做到以下几点:

from dataclasses import dataclass, field

@dataclass
class Example:
    a: int
    b: int = field(default_factory=lambda: 2)
    c: int = field(default_factory=lambda: 3)
    d: int = field(default_factory=lambda: 4)

问题:

1.有没有更清洁的方法来实现这一点? default_factory的这种用法是否被认为是不可读的?

2. 为什么有人想要一个既是 class 属性又是实例属性的字段?

谢谢!

这在文档中都有解释,尽管它在整个文档中有些分散。

描述可变默认值的部分说

Python 将默认成员变量值存储在 class 属性中。

由于a没有默认值,因此没有相应的 class 属性。

然后它显示了一个示例:

@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

请记住,参数默认值是在定义function 时评估的,而不是在调用它时评估的。 所以重新分配Dx不会改变构造新实例时使用的默认值。 (本节中的示例说明了一个不同的问题:使用默认值创建的所有实例将共享对同一列表的引用;请参阅“Least Astonishment”和 Mutable Default Argument )。

dataclasses.field的描述说:

如果通过调用field()指定了字段的默认值,则该字段的 class 属性将被指定的默认值替换。 如果未提供默认值,则将删除 class 属性。 目的是在 dataclass dataclass()装饰器运行后, class 属性将全部包含字段的默认值,就像指定了默认值本身一样。

这解释了为什么 c 有一个c属性,但没有d 使用default_factory时没有 class 属性,因为此默认值是通过在需要默认值时调用 function 动态生成的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM