如何使用 __future__ 注释从 self.__annotations__ 获取可调用的类对象?
Posted
技术标签:
【中文标题】如何使用 __future__ 注释从 self.__annotations__ 获取可调用的类对象?【英文标题】:How to get callable class objects from self.__annotations__ with __future__ annotations? 【发布时间】:2021-11-01 01:30:14 【问题描述】:如果使用 py3.10 from __future__ import annotations
,从注释中查找类的最佳方法是什么?以前,self.__annotations__[name]
会给你一个对象,但现在它返回一个字符串。如图所示,您可以使用globals()
,但这对我来说似乎不合适。有没有更好的办法?
@dataclass
class Person:
height: float
def stack(self, other: Person):
return Person(self.height + other.height) #gymnasts
@dataclass
class Chair:
height: float
def stack(self, other: Chair):
return Chair(0.6*(self.height + other.height) ) #stackable chairs
@dataclass
class Room:
person: Person
chair: Chair
def set(self, name: str, val: float):
# lots of complicated validation
# factory = self.__annotations__[name] # this worked before from __future__ import annotations
factory = globals()[self.__annotations__[name]]
self.__setattr__(name, factory(height=val))
【问题讨论】:
【参考方案1】:使用typing.get_type_hints
访问“函数、方法、模块或类对象”的评估__annotations__
。值得注意的是,它知道基本的继承——它合并继承的注解并使用当前类的globals
而不是方法的模块。
@dataclass
class Room:
person: Person
chair: Chair
def set(self, name: str, val: float):
factory = get_type_hints(type(self))[name]
self.__setattr__(name, factory(height=val))
虽然typing.get_type_hints
比仅检查globals
做了一些额外的工作,但__future__.annotations
本质上会擦除非全局信息。对于在locals
范围内定义的类的罕见情况,必须显式提供命名空间。
【讨论】:
不错。 “__future__.annotations
固有地擦除非全局信息”是什么意思?
@mmdanziger pre-__future__.annotations
和 PEP 649 注解根据 Python 的正常作用域规则捕获注解;例如,这意味着它们可以捕获仅在函数内部定义的类型。 __future__.annotations
不捕获任何内容,因此函数局部类型将超出函数的范围; typing.get_type_hints
无法获取此类类型。以上是关于如何使用 __future__ 注释从 self.__annotations__ 获取可调用的类对象?的主要内容,如果未能解决你的问题,请参考以下文章
py2.7 from __future__ import error