我可以在带批注注释评估的Python类型提示中使用__qualname__吗?
我喜欢使用__qualname__
作为工厂样式类方法的返回类型注释,因为它不对类名进行硬编码,因此保留了有效的子类(请参见.
I like using __qualname__
for the return-type annotation of factory-style class methods, because it doesn't hardcode the classname and therefore keeps working subclasses (cf. this answer).
class Foo:
@classmethod
def make(cls) -> __qualname__:
return cls()
当前这似乎可以很好地工作,但是我不确定通过推迟对批注的评估(说,
Currently this seems to work fine, but I am not sure whether this will still be possible with the postponed evaluation of annotations (PEP 563): the PEP says that
注释只能使用模块作用域中存在的名称,因为使用本地名称的延迟评估不可靠(唯一的例外是由
typing.get_type_hints()
解析的类级名称).
Annotations can only use names present in the module scope as postponed evaluation using local names is not reliable (with the sole exception of class-level names resolved by
typing.get_type_hints()
).
PEP还说:
get_type_hints()
函数自动为函数和类解析正确的globalns
值.它还会自动为类提供正确的localns
.
The
get_type_hints()
function automatically resolves the correct value ofglobalns
for functions and classes. It also automatically provides the correctlocalns
for classes.
但是,以下代码
from __future__ import annotations
import typing
class Foo():
@classmethod
def make(cls) -> __qualname__:
return cls()
print(typing.get_type_hints(Foo.make))
失败
File "qualname_test.py", line 11, in <module>
print(typing.get_type_hints(Foo.make))
File "/var/local/conda/envs/py37/lib/python3.7/typing.py", line 1004, in get_type_hints
value = _eval_type(value, globalns, localns)
File "/var/local/conda/envs/py37/lib/python3.7/typing.py", line 263, in _eval_type
return t._evaluate(globalns, localns)
File "/var/local/conda/envs/py37/lib/python3.7/typing.py", line 467, in _evaluate
eval(self.__forward_code__, globalns, localns),
File "<string>", line 1, in <module>
NameError: name '__qualname__' is not defined
注释__future__
导入使代码再次工作,在这种情况下,它将输出
Commenting the __future__
import makes the code work again, in that case it outputs
{'return': <class '__main__.Foo'>}
符合预期.
我的用例__qualname__
是否受支持(这意味着get_type_hints
有问题),还是PEP 563无法使用这种方法?
Is my use case __qualname__
supported (which would mean that get_type_hints
is buggy), or is this approach not possible with PEP 563?
Foo.make
并不总是返回Foo
的实例(__qualname__
扩展为该实例).它返回作为参数接收的类的实例,不一定是Foo
.考虑:
Foo.make
doesn't always return an instance of Foo
(which is what __qualname__
expands to). It returns an instance of the class it receives as an argument, which isn't necessarily Foo
. Consider:
>>> class Foo:
... @classmethod
... def make(cls):
... return cls()
...
>>> class Bar(Foo):
... pass
...
>>> type(Bar.make())
<class '__main__.Bar'>
正确的类型提示应该是类型变量:
The correct type hint would be a type variable:
T = TypeVar("T", bound="Foo")
class Foo:
@classmethod
def make(cls: Type[T]) -> T:
return cls()