python 数据类 `__init_subclass__` 不从子类加载字段
python dataclass `__init_subclass__` does not load the fields from subclass
请检查下面的代码
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__
还没有子类中字段的概念,因为它没有被加载。请让我知道如何获得预期的输出。
因此,装饰器的工作方式如下:
@some_decorator
class A:
pass
相当于:
class A:
pass
A = some_decorator(A)
因此,dataclass
装饰器 将 __dataclass_fields__
属性添加到 class 对象 时没有 运行 __init_subclass__
运行s,因为已经创建了整个 class 个对象。
您 可以 手动检查 __annotations__
(无论如何 dataclass
都依赖于创建 field
对象)。请注意,您将必须手动检查 MRO 中的所有 classes,注意以相反的顺序进行检查并防止可能缺少注释的 classes,例如:
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'>
请检查下面的代码
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__
还没有子类中字段的概念,因为它没有被加载。请让我知道如何获得预期的输出。
因此,装饰器的工作方式如下:
@some_decorator
class A:
pass
相当于:
class A:
pass
A = some_decorator(A)
因此,dataclass
装饰器 将 __dataclass_fields__
属性添加到 class 对象 时没有 运行 __init_subclass__
运行s,因为已经创建了整个 class 个对象。
您 可以 手动检查 __annotations__
(无论如何 dataclass
都依赖于创建 field
对象)。请注意,您将必须手动检查 MRO 中的所有 classes,注意以相反的顺序进行检查并防止可能缺少注释的 classes,例如:
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'>