我可以在带批注注释评估的Python类型提示中使用__qualname__吗? [英] Can I use __qualname__ in a Python type hint with postponed annotation evaluation?

查看:471
本文介绍了我可以在带批注注释评估的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 of globalns for functions and classes. It also automatically provides the correct localns 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()

这篇关于我可以在带批注注释评估的Python类型提示中使用__qualname__吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆