如何获取Python变量注释?

Kam*_*yar 8 python type-annotation

在使用带注释字段定义类/模块时,如何像函数中那样获取注释?

class Test:
  def __init__(self):
    self.x : int
t = Test()
Run Code Online (Sandbox Code Playgroud)

现在我需要从 getattr(t,'x')

Sha*_*ger 5

使用基准Python,在不更改的定义的情况下,您无法做任何选择Test。最小的更改是在类级别注释属性:

class Test:
    x: int
    def __init__(self):
        # define self.x or not, but it needn't be annotated again
Run Code Online (Sandbox Code Playgroud)

实际上,这很好。默认情况下,假定在类范围内的批注是指实例属性,而不是属性(在类范围内分配值将创建类属性,但不对其进行注释);您必须显式地使用它typing.ClassVar来表示带注释的类型仅打算用作类属性。PEP 526关于类和实例变量注释的部分定义了这些行为;它们是您可以依靠的,而不仅仅是偶然的实现。

一旦你做到了这一点,typing.get_type_hints将返回{'x': int}两个Testt在你的榜样情况。

虽然这是对自己够了,我会注意到,在很多这样的情况如今,只要你标注无论如何,你可以用简化代码dataclasses模块,获得以最小的打字为您定义的注释和基本功能。适用于您的情况的简单替换代码为:

import dataclasses

@dataclasses.dataclass
class Test:
    x: int
Run Code Online (Sandbox Code Playgroud)

尽管您的手机壳没有展示完整的功能集(基本上只是用__init__装饰器代替了),但它的作用还远远不止于此。除了__init__为您定义(它希望收到一个带有x注释的参数int)以及一个合适的__repr__和之外__eq__,您还可以轻松定义默认值(只需在注释点或更复杂或易变的情况下分配默认值,分配一个dataclasses.field替代值),然后您可以传递参数dataclass以使其产生可排序或不可变的实例。

在您的情况下,主要优点是消除冗余;x注释和引用只进行一次,而不是在类级别进行一次注释,然后在初始化期间使用(并且可选地,再次进行注释)。


nor*_*ok2 3

我不确定您是否可以self.x轻松获得注释。

假设你的代码:

class Test:
    def __init__(self):
        self.x: int = None

t = Test()
Run Code Online (Sandbox Code Playgroud)

我尝试寻找__annotations__inTestt(我期望它在哪里),但运气不佳。

但是,您可以采取以下解决方法:

class Test:
    x: int
    def __init__(self):
        # annotation from here seems to be unreachable from `__annotations__`
        self.x: str

t = Test()

print(Test.__annotations__)
# {'x': <class 'int'>}
print(t.__annotations__)
# {'x': <class 'int'>}
Run Code Online (Sandbox Code Playgroud)

编辑

如果您希望能够检查@ruohola 的检查答案self.x内的类型。mypy


编辑2

请注意,mypy(至少 v.0.560)确实x因为从 theclass和 从 the进行注释而感到困惑__init__,即,看起来 的注释self.x被大胆地忽略了:

import sys

class Test:
    x: str = "0"
    def __init__(self):
        self.x: int = 1

t = Test()

print(Test.x, t.x)
# 0 1
print(Test.x is t.x)
# False

if "mypy" in sys.modules:
    reveal_type(t.x)
    # from mypyp: annotated_self.py:14: error: Revealed type is 'builtins.str'
    reveal_type(Test.x)
    # from mypy: annotated_self.py:15: error: Revealed type is 'builtins.str'

Test.x = 2
# from mypy: annotated_self.py:17: error: Incompatible types in assignment (expression has type "int", variable has type "str")

t.x = "3"
# no complaining from `mypy`
t.x = 4
# from mypy: annotated_self.py:19: error: Incompatible types in assignment (expression has type "int", variable has type "str")

print(Test.x, t.x)
# 2 4
Run Code Online (Sandbox Code Playgroud)