【问题标题】:Class Attribute and metaclass in dataclasses数据类中的类属性和元类
【发布时间】:2020-01-17 20:11:51
【问题描述】:

我有一些带有类属性和元类的 Python 类:

from abc import ABCMeta

class OldProduct(metaclass=ABCMeta):
    c_type: str
    c_brand: str

    def __init__(self, name:str):
        self.name = name

class OldLegoBox(OldProduct):
    c_type = "Toy"
    c_brand = "Lego"

    def __init__(self, name:str, price:float):
        self.name = name
        self.price = price

oldbox1 = OldLegoBox("Princess", 12.3)
print(oldbox1.c_brand)
oldbox2 = OldLegoBox("Knight", 42.3)
print(oldbox2.c_brand)

我想用dataclasses改进代码:如何处理c_typec_brand的类属性?

我正在考虑以下似乎可以满足我的需求:

from abc import ABCMeta
from dataclasses import dataclass, field


@dataclass
class Product(metaclass=ABCMeta):
    c_type: str
    c_brand: str
    name: str


@dataclass
class LegoBox(Product):
    name: str
    price: float
    c_type: str = field(default="Toy", init=False)
    c_brand: str = field(default="Lego", init=False)


box1 = LegoBox("Princess", 12.3)
print(box1)
box1.price = 1000
box1.name = "toto"
box1.c_brand = "some brand"
print(box1)
box2 = LegoBox("Knight", 42.3)
print(box2)

有没有更合适的方法?

【问题讨论】:

    标签: python python-dataclasses


    【解决方案1】:

    Dataclass class variables 应使用 typing.ClassVar 注释

    @dataclass
    class Product(metaclass=ABCMeta):
        c_type: ClassVar[str]
        c_brand: ClassVar[str]
        name: str
    
    @dataclass
    class LegoBox(Product):
        c_type: ClassVar[str] = "Toy"
        c_brand: ClassVar[str] = "Lego"
        price: float
    

    据我所知,使用抽象类实际上并不能得到任何东西,因为没有抽象方法。您仍然可以创建Product 的实例,但它们不会具有c_typec_brand 属性。

    【讨论】:

    • 谢谢。是的,这个例子并没有突出元类的兴趣。我想从我们使用的代码中提取一小部分内容。
    • 有些惊讶地发现 typing 模块中的某些东西具有运行时效果
    • 更多的是dataclass 装饰器检查类型提示并使用它们生成代码。 ClassVar 实际上并没有做任何事情,而是使用它的代码在看到 ClassVar 时知道该做什么。
    猜你喜欢
    • 2021-08-21
    • 1970-01-01
    • 1970-01-01
    • 2021-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-30
    • 1970-01-01
    相关资源
    最近更新 更多