首页 > 解决方案 > 类 __annotations__ 中的条目顺序是否与其定义一致?

问题描述

假设我们有一个类定义:

class A:
    z: 1
    b: 2
    Z: 3
    g: 4
    C: 5
    A: 6
    d: 7

标准 CPython 给出了这个值A.__annotations__

{
    'z': 1,
    'b': 2,
    'Z': 3,
    'g': 4,
    'C': 5,
    'A': 6,
    'd': 7
}

总是这样吗?规范对此有何评论?

标签: pythonannotations

解决方案


PEP 526中给出的变量注释语法规范说明了以下内容:

在模块或类级别,如果被注释的项目是一个简单的名称,那么它和注释将__annotations__ 作为从名称到评估的注释的有序映射存储在该模块或类的属性中(如果私有则被破坏)。

因此,默认情况下似乎可以保证有序映射。但是,PEP 还声明了以下内容:

__annotations__是可写的...但是尝试更新 __annotations__到有序映射以外的其他内容可能会导致 TypeError ...(请注意,对__annotations__ ... 的赋值被 Python 解释器接受而不会质疑它 - 但随后的类型注释需要它成为一个 MutableMapping ...)

因此,由于 aMutableMapping本身不是有序的,因此__annotations__第三方类的 至少有可能是定义任意顺序的映射:

from collections.abc import MutableMapping

class D(MutableMapping):
    def __init__(self, *args):
        self._d = {}

    def __getitem__(self, key):
        return self._d[key]

    def __setitem__(self, key, value):
        self._d[key] = value

    def __delitem__(self, key):
        del self._d[key]

    def __iter__(self):
        return reversed(self._d)

    def __len__(self):
        return len(self._d)


class A:
    __annotations__ = D()
    z: 1
    b: 2
    Z: 3
    g: 4
    C: 5
    A: 6
    d: 7

for item in A.__annotations__.items():
    print(item)
('d', 7)
('A', 6)
('C', 5)
('g', 4)
('Z', 3)
('b', 2)
('z', 1)
    
    

推荐阅读