如何访问父 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.)