【问题标题】:Proper way to create class variable in Data Class在数据类中创建类变量的正确方法
【发布时间】:2020-09-08 06:16:00
【问题描述】:

我刚刚开始使用 Python 的数据类,我想确认我正在以正确的方式声明类变量。

使用常规 python 类

class Employee:

    raise_amount = .05

    def __init__(self, fname, lname, pay):
        self.fname = fname
        self.lname = lname
        self.pay = pay

使用 python 数据类

@dataclass
class Employee:
    fname: str
    lname: str
    pay: int
    raise_amount = .05

我指的类变量是raise_amount。这是使用数据类正确声明的类变量吗?或者有更好的方法吗?

我已经测试了数据类实现,它提供了预期的功能,但我主要想知道我的实现是否遵循最佳实践。

【问题讨论】:

  • 如果您不想从 exter 访问它,请在名称前添加两个下划线,例如:“__raise_amout”
  • “exter”是什么意思?我想要的是一个为 Employee 类的所有实例通用设置的变量。
  • 对于一般类是,但对于数据类不是! dataclass 将创建有界属性
  • 如果你声明了一个类属性并且你在任何方法中覆盖了它的值,那么这个属性将只对给定的实例有界。(如果你在那个实例上调用那个方法)
  • 使用name mangling 模拟数据类中的类变量是一种完全错误的方法,接受的typing.ClassVar 要好得多。

标签: python python-3.x python-dataclasses


【解决方案1】:

要创建类变量,请将字段注释为 typing.ClassVar 或根本不注释。

from typing import ClassVar

@dataclass
class Foo:
    ivar: float = 0.5
    cvar: ClassVar[float] = 0.5
    nvar = 0.5

foo = Foo()
Foo.ivar, Foo.cvar, Foo.nvar = 1, 1, 1
print(Foo().ivar, Foo().cvar, Foo().nvar)   # 0.5 1 1
print(foo.ivar, foo.cvar, foo.nvar)         # 0.5 1 1

有一个细微的区别,@dataclass 完全忽略了未注释的字段,而 ClassVar 字段被存储但不转换为属性。


dataclasses — Data Classes

成员变量 [...] 使用 PEP 526 类型注释定义。

Class variables

dataclass() 实际检查 a 类型的两个地方之一 field 用于确定字段是否为 PEP 中定义的类变量 526. 它通过检查字段的类型是否为typing.ClassVar 来做到这一点。 如果字段是ClassVar,则将其排除在外 考虑作为一个字段,并被数据类机制忽略。 模块级不返回此类ClassVar 伪字段 fields() 函数。

【讨论】:

  • 我的原始设置raise_amount = .05 似乎与raise_amount: ClassVar[float] = .05 具有相同的功能。如果缺少数据类型,您是否知道它是否自动假定变量是类变量?不过,我确实喜欢您的实现更加明确。
  • 如果一个变量没有注解,它会被dataclass完全忽略。这也有效地使它成为一个类变量。
  • 明白了,有道理。谢谢你。我认为最好让事情变得明显,所以你的方法可能是要走的路。非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-18
  • 2014-11-10
  • 1970-01-01
  • 2012-02-21
  • 2021-11-04
相关资源
最近更新 更多