如何访问父 class 的 __annotations__?
How can I access to __annotations__ of parent class?
有什么方法可以访问父 class 的键入 __annotations __?
在上面的示例中,class Student
继承自 class Person
,但它不包含来自 Person
class.
class Person:
name: str
address: str
def __init__(self):
print(self.__annotations__)
class Student(Person):
year: int
person = Person()
# {'name': <class 'str'>, 'address': <class 'str'>}
student = Student()
# {'year': <class 'int'>}
# HERE I would expect the name and the address props
self.__annotations__
,在没有名为 __annotations__
的实例属性的情况下,等同于 type(self).__annotations__
。由于定义了 Student.__annotations__
,因此没有理由寻找 Person.__annotations__
。您需要检查 MRO 中的每个 class。最简单的方法是在某些基础 class 中定义一个 class 方法(或者使它成为一个不与任何单个 class 关联的外部函数)。
class Person:
name: str
address: str
@classmethod
def get_annotations(cls):
d = {}
for c in cls.mro():
try:
d.update(**c.__annotations__)
except AttributeError:
# object, at least, has no __annotations__ attribute.
pass
return d
def __init__(self):
print(self.get_annotations())
class Student(Person):
year: int
这是 Google 搜索将我带到这里时我希望看到的答案。
from collections import ChainMap
def all_annotations(cls) -> ChainMap:
"""Returns a dictionary-like ChainMap that includes annotations for all
attributes defined in cls or inherited from superclasses."""
return ChainMap(*(c.__annotations__ for c in cls.__mro__ if '__annotations__' in c.__dict__) )
与@chepner 的方法不同,这可以正确处理多个 superclasses 为同一属性名称提供不同注释的情况(这通常是不可取的,但可能没问题,例如当 subclass 给出具有更具体注释的属性)。 @chepner 的方法将优先考虑方法解析顺序 (MRO) 中 last 出现的注释,而 Python 的 class 继承通常优先考虑任何一个class 按此顺序排在 前面 。 (如果您确实想使用@chepner 的方法,您最好在 MRO 的 reverse 中更新注释,注意不要意外丢失在此定义的任何注释class.)
有什么方法可以访问父 class 的键入 __annotations __?
在上面的示例中,class Student
继承自 class Person
,但它不包含来自 Person
class.
class Person:
name: str
address: str
def __init__(self):
print(self.__annotations__)
class Student(Person):
year: int
person = Person()
# {'name': <class 'str'>, 'address': <class 'str'>}
student = Student()
# {'year': <class 'int'>}
# HERE I would expect the name and the address props
self.__annotations__
,在没有名为 __annotations__
的实例属性的情况下,等同于 type(self).__annotations__
。由于定义了 Student.__annotations__
,因此没有理由寻找 Person.__annotations__
。您需要检查 MRO 中的每个 class。最简单的方法是在某些基础 class 中定义一个 class 方法(或者使它成为一个不与任何单个 class 关联的外部函数)。
class Person:
name: str
address: str
@classmethod
def get_annotations(cls):
d = {}
for c in cls.mro():
try:
d.update(**c.__annotations__)
except AttributeError:
# object, at least, has no __annotations__ attribute.
pass
return d
def __init__(self):
print(self.get_annotations())
class Student(Person):
year: int
这是 Google 搜索将我带到这里时我希望看到的答案。
from collections import ChainMap
def all_annotations(cls) -> ChainMap:
"""Returns a dictionary-like ChainMap that includes annotations for all
attributes defined in cls or inherited from superclasses."""
return ChainMap(*(c.__annotations__ for c in cls.__mro__ if '__annotations__' in c.__dict__) )
与@chepner 的方法不同,这可以正确处理多个 superclasses 为同一属性名称提供不同注释的情况(这通常是不可取的,但可能没问题,例如当 subclass 给出具有更具体注释的属性)。 @chepner 的方法将优先考虑方法解析顺序 (MRO) 中 last 出现的注释,而 Python 的 class 继承通常优先考虑任何一个class 按此顺序排在 前面 。 (如果您确实想使用@chepner 的方法,您最好在 MRO 的 reverse 中更新注释,注意不要意外丢失在此定义的任何注释class.)