【问题标题】:python dataclass `__init_subclass__` does not load the fields from subclasspython数据类`__init_subclass__`不从子类加载字段
【发布时间】:2020-04-05 06:27:31
【问题描述】:

请检查下面的代码

import dataclasses


@dataclasses.dataclass
class A:
    a: int = 10

    def __init_subclass__(cls, **kwargs):
        for f in dataclasses.fields(cls):
            print("     ", cls, f.name)


print("Defining Subclass B")


@dataclasses.dataclass
class B(A):
    b: int = 100


print("Defining Subclass C")


@dataclasses.dataclass
class C(B):
    c: int = 1000

输出是

Defining Subclass B
      <class '__main__.B'> a
Defining Subclass C
      <class '__main__.C'> a
      <class '__main__.C'> b

我期待

Defining Subclass B
      <class '__main__.B'> a
      <class '__main__.B'> b
Defining Subclass C
      <class '__main__.C'> a
      <class '__main__.C'> b
      <class '__main__.C'> c

显然,dunder 方法__init_subclass__ 还没有子类中的字段的概念,因为它没有加载。请让我知道如何获得预期的输出。

【问题讨论】:

  • 今后,除了任何特定于版本的标签外,请对所有与python相关的问题使用通用的[python]标签

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


【解决方案1】:

因此,装饰器的工作方式如下:

@some_decorator
class A:
    pass

相当于:

class A:
   pass
A = some_decorator(A)

所以,dataclass 装饰器__dataclass_fields__ 属性添加到类对象__init_subclass__ 运行时并没有运行,因为已经创建了整个类对象。 p>

可以手动检查__annotations__(这是dataclass 依赖于创建field 对象)。请注意,您必须手动检查 MRO 中的所有类,注意以相反的顺序进行检查并防止潜在的缺少注释的类,例如:

import dataclasses


@dataclasses.dataclass
class A:
    a: int = 10

    def __init_subclass__(cls, **kwargs):
        for klass in  reversed(cls.mro()):
            # in case a base class lacks annotations, e.g. object
            annotations = getattr(klass, '__annotations__', {})
            for name, value in annotations.items():
                print("     ", cls, name, value)

print("Defining Subclass B")


@dataclasses.dataclass
class B(A):
    b: int = 100


print("Defining Subclass C")


@dataclasses.dataclass
class C(B):
    c: int = 1000

可以为你工作。

上面为我打印了以下输出:

Defining Subclass B
      <class '__main__.B'> a <class 'int'>
      <class '__main__.B'> b <class 'int'>
Defining Subclass C
      <class '__main__.C'> a <class 'int'>
      <class '__main__.C'> b <class 'int'>
      <class '__main__.C'> c <class 'int'>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-05
    • 1970-01-01
    • 1970-01-01
    • 2021-10-03
    • 1970-01-01
    • 2016-02-26
    • 2022-06-16
    • 1970-01-01
    相关资源
    最近更新 更多