【发布时间】:2021-10-03 17:14:16
【问题描述】:
我正在开发一个当前支持 Python 3.6+ 的库,但在 Python 3.6 的 typing 模块中如何定义前向引用时遇到了一些麻烦。我在本地 Windows 机器上设置了pyenv,以便我可以轻松地在不同的 Python 版本之间切换以进行本地测试,因为我的系统解释器默认为 Python 3.9。
这里的用例本质上是我试图用有效的前向引用类型定义一个TypeVar,然后我可以将其用于类型注释目的。当我在 3.7+ 上并直接从 typing 模块导入 ForwardRef 时,我已经确认以下代码运行没有问题,但是我无法在 Python 3.6 上得到它,因为我注意到由于某种原因,前向引用不能用作TypeVar 的参数。我也尝试将 forward ref 类型作为参数传递给 Union ,但我遇到了类似的问题。
这里是TypeVar 的导入和定义,我正在尝试在 python 3.6.0 以及更新的版本(如 3.6.8)上工作 - 我确实注意到我在次要版本之间遇到了不同的错误:
from typing import _ForwardRef as PyForwardRef, TypeVar
# Errors on PY 3.6:
# 3.6.2+ -> AttributeError: type object '_ForwardRef' has no attribute '_gorg'
# 3.6.2 or earlier -> AssertionError: assert isinstance(a, GenericMeta)
FREF = TypeVar('FREF', str, PyForwardRef)
这是我已经能够测试出来的示例用法,它似乎可以按预期对 Python 3.7+ 进行类型检查:
class MyClass: ...
def my_func(typ: FREF):
pass
# Type checks
my_func('testing')
my_func(PyForwardRef('MyClass'))
# Does not type check
my_func(23)
my_func(MyClass)
到目前为止我做了什么
这是我目前用来支持 Python 3.6 的解决方法。这并不漂亮,但似乎至少可以让代码运行而没有任何错误。然而,这似乎并没有按预期进行类型检查 - 至少在 Pycharm 中没有。
import typing
# This is needed to avoid an`AttributeError` when using PyForwardRef
# as an argument to `TypeVar`, as we do below.
if hasattr(typing, '_gorg'): # Python 3.6.2 or lower
_gorg = typing._gorg
typing._gorg = lambda a: None if a is PyForwardRef else _gorg(a)
else: # Python 3.6.3+
PyForwardRef._gorg = None
想知道我是否走在正确的轨道上,或者是否有更简单的解决方案可用于支持 ForwardRef 类型作为 Python 3.6 中 TypeVar 或 Union 的参数。
【问题讨论】:
标签: python python-3.x type-hinting forward-declaration python-typing