我想使用一个同时具有Enum
和Enum
成员的集合。但是,当我尝试访问特殊属性__name__
时,我找不到一种不会导致mypy错误的方法来编写它。(请参阅__name__
何时可以是预期类型和成员的列表。(
关于上下文,BDFL在mypy第3728期中给出了关于发生了什么的简短解释。基本上,当您对具有不同类型项的集合进行迭代时,它们是联接的。因此,在下一个例子中,mypy所说的是Enum和Enum成员连接到object
。。。
示例1:
from enum import Enum
from typing import Type
class Color(Enum):
RED = 1
my_collection: tuple[Type[Color], Color] = (Color, Color.RED)
for item in my_collection:
if item is Color:
print(item.__name__)
mypy给出错误:
错误:"对象";没有属性"__名称__";;也许"__ne__";或"__new__"?
示例2:
接下来,我试图在for循环中注释变量,看看mypy错误是否获得了更多的颜色。。。
from enum import Enum
from typing import Type, Union
class Color(Enum):
RED = 1
my_collection: tuple[Type[Color], Color] = (Color, Color.RED)
item: Union[Type[Color], Color]
for item in my_collection:
if item is Color:
print(item.__name__)
这一次mypy给出了两个错误,第一个是由for循环中不兼容的类型引起的(有道理(,第二个是可预期的错误,表示Enum成员没有__name__
特殊属性。
错误:赋值中的类型不兼容(表达式的类型为"object",变量的类型为Union[type[Color],Color]"(
错误:项目";颜色";的";Union[Type[Color];没有属性"__名称__">
示例3:
我的下一步是在使用__name__
之前尝试键入.cast,这通常足以让mypy限制类型。。。
from enum import Enum
from typing import Type, cast
class Color(Enum):
RED = 1
my_collection: tuple[Type[Color], Color] = (Color, Color.RED)
for item in my_collection:
if item is Color:
item = cast(Type[Color], item)
print(item.__name__)
这次的错误是:
错误:没有属性"__名称__";
这3个例子在运行时可以工作,但是Python对具有不同类型项的集合进行迭代的方式是什么?这些项不会导致mypy错误?(使用默认配置的Python 3.9和mypy 0.812。(
我查看了MyPy的GitHub上的几个问题,学到了两件事:
根据Guido的说法,<nothing>
不应显示在输出中<nothing>
意味着MyPy union’ed the types(对于item
,它是Type[Color]
和Color
(,结果为nothing(即"空集"(,因此它键入nothing。换句话说,MyPy在强制转换后无法计算item
的有用类型,请参阅:reveal_type(my_collection[0]) reveal_type(my_collection[1]) for item in my_collection: if item is Color: reveal_type(item) item = cast(Type[Color], item) reveal_type(item) print(item.__name__)
我认为你达到了工具的极限。你可以在GitHub上发布一个问题$ mypy -V; mypy so70636782.py mypy 0.931 so70636782.py:9: note: Revealed type is "Type[so70636782.Color]" so70636782.py:10: note: Revealed type is "so70636782.Color" so70636782.py:13: note: Revealed type is "builtins.object" so70636782.py:15: note: Revealed type is "<nothing>" so70636782.py:16: error: <nothing> has no attribute "__name__" Found 1 error in 1 file (checked 1 source file)
MyPy在我的经验中对并集不是很好,所以我建议你只使用元组是类型对的事实:
color_class, color = my_collection # unpacking
print(color_class.__name__)
通过这种方式,MyPy可以单独跟踪每个变量,每个变量都有一个类型。