python - 非泛型类型的不同运行时行为
问题描述
考虑以下两种情况:
from queue import Queue
my_q: Queue[int] = Queue()
print(f"queue={my_q}")
和
from queue import Queue
class MyClass(object):
def __init__(self):
self.my_q: Queue[int] = Queue()
my_class = MyClass()
print(f"queue={my_class.my_q}")
运行前者(预期)会抛出TypeError
:
$ python3 run.py
Traceback (most recent call last):
File "test.py", line 3, in <module>
my_q: Queue[int] = Queue()
TypeError: 'type' object is not subscriptable
然而后者没有,并且没有问题地继续打印语句:
$ python3 run.py
queue=<queue.Queue object at 0x7fb40265f730>
我希望TypeError
在这两种情况下都有一个。TypeError
当Queue[int]
类型在类的方法内部时,为什么没有__init__
?
解决方案
模块和类注释都可以在运行时访问,因此可以评估:
# example.py
a: int = 4
print(__annotations__) # {'a': <class 'int'>}
相反,函数的本地注释是不可访问的,因此永远不会被评估。
根据PEP 3107,函数参数注释在运行时被评估并可用:
编译后,函数的注释可通过函数的
__annotations__
属性获得。
根据PEP 526 ,简单名称的模块和类级别注释在运行时进行评估和可用。为了提高效率,函数内部的注释没有被明确地评估或存储:
此外,在模块或类级别,如果被注释的项目是一个简单的名称,那么它和注释将
__annotations__
作为从名称到评估的注释的有序映射存储在该模块或类的属性中(如果私有,则被破坏) .
[...]
此外,在本地提供注释的价值并不能抵消必须在每个函数调用上创建和填充注释字典的成本。因此,功能级别的注释不会被评估和存储。
使用PEP 563 / Python 3.10,不再立即评估注释。但是,模块、类和函数参数名称的注释仍然可能被延迟评估,因此应该是有效的表达式。函数的局部注释仍然无法访问,因此无法评估。
请注意,根据 PEP 526,根本不评估局部变量注释,因为它们在函数闭包之外无法访问。
推荐阅读
- ruby-on-rails - Rails ActiveRecord:如何在单个查询中选择每天、多天的前 X 条记录?
- asp.net-core - AD B2C 索赔中的最新成员组
- html - HTML CSS 对齐 div 内联的项目
- geometry - 如何在一个查询中包含三个几何图形 - PostGIS
- asp.net-core - .Net Core Blazor 如何传递多个参数?
- ios - 登录后不显示sideMenu
- javascript - 类型参数不可分配给字符串
- python - Python WebScraper - 对象没有属性'urlretrieve'
- azure - Azure 和 Flysystem 中异步客户端的 GuzzleHttp 并行进度
- if-statement - 显示 VLOOKUP 的最后一个值