提问人:Zacharias030 提问时间:6/12/2023 最后编辑:Zacharias030 更新时间:6/12/2023 访问量:278
如何在python中定义通过ForwardRef延迟计算的类型别名(TypeAlias)?
How to define a type alias (TypeAlias) that is evaluated lazily via ForwardRef in python?
问:
我的目标是防止在使用类型别名时在运行时导入昂贵的模块。
如果没有别名,可以将昂贵的模块隐藏在后面,并使导入成为相应函数的本地:typing.TYPE_CHECKING
# utils.py -- module that must be very lightweight to import
from typing import TYPE_CHECKING
if TYPE_CHECKING:
import tensorflow as tf # lot's of unwanted side-effects
def rarely_used_function(t: "tf.Tensor"): # <-- note the lazily evaluated type hint
import tensorflow as tf
...
在定义类型别名时,如何实现相同的效果?
# types.py -- a collection of our own type aliases
from typing import TYPE_CHECKING, TypeAlias
if TYPE_CHECKING:
import tensorflow as tf
MyTensorAlias = "tf.Tensor" # <-- now this is just a string assignment and will not evaluate to a `ForwardRef`
# Notes of things that do not work:
# 1) annotating with TypeAlias
MyOtherTensorAlias: TypeAlias = "tf.Tensor" # <-- still just a str and will cause runtime errors
# 2) Aliases behind `TYPE_CHECKING`
if TYPE_CHECKING:
MyLazyTensorAlias = tf.Tensor # <-- this is fine for static type checkers, but raises at runtime when `types has no member MyLazyTensorAlias` anymore.
可以使用 实现延迟评估,但是子类型不是我想要的(因为这样我需要强制转换所有用户,例如 .typing.NewType()
Subtype(tf.Tensor(...))
编辑:
它在运行时失败的方式特定于新运算符。
考虑:|
Python 3.10.8 (main, Nov 24 2022, 08:09:04) [Clang 14.0.6 ]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.7.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: from typing import TypeAlias
...: Alias: TypeAlias = "Original"
...: def func(a: Alias | None):
...: pass
...:
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Cell In[1], line 3
1 from typing import TypeAlias
2 Alias: TypeAlias = "Original"
----> 3 def func(a: Alias | None):
4 pass
TypeError: unsupported operand type(s) for |: 'str' and 'NoneType'
In [2]: from typing import TypeAlias,Optional
...:
...: Alias: TypeAlias = "Original"
...: def func(a: Optional[Alias]):
...: pass
...:
In [3]: class Original:
...: pass
...:
In [4]: def func(a: Original | None):
...: pass
...:
答:
0赞
Zacharias030
6/12/2023
#1
正如@Jasminj所指出的,应该可以工作,但请注意,文档指出类型联合 via 不能与正向引用 (https://docs.python.org/3/library/stdtypes.html#union-type 一起使用MyOtherTensorAlias: TypeAlias = "tf.Tensor"
X | Y
)
评论
1赞
dROOOze
6/13/2023
|
没问题,你只需要把整个表达式放在一个字符串中。.更好的是,放在模块的顶部,你不需要在注释表达式中使用任何字符串。"MyOtherTensorAlias | None"
from __future__ import annotations
评论
MyTensorAlias = ForwardRef("tf.Tensor")
MyTensorAlias = TypeAlias("tf.Tensor")
MyOtherTensorAlias: TypeAlias = "tf.Tensor"
应该根据文档工作。你会得到什么样的运行时错误?(请附上示例代码+回溯)TypeError: Cannot instantiate typing.TypeAlias
Type | None
from typing import TypeAlias; Alias: TypeAlias = "Original"; def func(a: Alias | None): pass; # -----> TypeError: unsupported operand type(s) for |: 'str' and 'NoneType'