输入对枚举成员有效的协议

问题描述 投票:0回答:1

接受应与协议匹配的枚举器类型的正确类型是什么? 我的意思是枚举器应该在协议中定义成员

这是一个简化的代码示例。

from typing import Protocol 
from enum import Enum 

class MyProto(Protocol):
   item1: int 
   item2: int 

def check_item1( e: MyProto, value:int):
    return e.item1 == value  

class MyEnum(int, Enum):
   item1 = 0 
   item2 = 1 
   other_item_not_in_protocol = 2 

check_item1( MyEnum,  0 ) #<-- pyright complains about everything :

Pyright 抱怨

# Argument of type "type[MyEnum]" cannot be assigned to parameter "e" of type "MyProto" #in function "check_item1"
#     "item1" is invariant because it is mutable
#     "item1" is an incompatible type
#     "item1" must be defined as a ClassVar to be compatible with protocol
#       "Literal[MyEnum.item1]" is incompatible with "int"
#     "item2" is invariant because it is mutable
#     "item2" is an incompatible type
#     "item2" must be defined as a ClassVar to be compatible with protocol
#       "Literal[MyEnum.item2]" is incompatible with "int" [reportArgumentType]

Mypy 也抱怨:

# error: Argument 1 to "check_item1" has incompatible type "type[MyEnum]"; expected # "MyProto"  [arg-type]
# Found 1 error in 1 file (checked 1 source file)
python enums python-typing
1个回答
0
投票

您需要三件事来进行此类型检查。

首先,使用

item1
item2
@property
设为只读:

class MyProto(Protocol):

    @property
    def item1(self) -> int:
        ...
    
    @property
    def item2(self) -> int:
        ...

引用规格:

默认情况下,上面定义的协议变量被认为是可读可写的。要定义只读协议变量,可以使用(抽象)属性。

协议成员 |协议、打字规范

其次,使用

ClassVar
明确指出
Enum
成员是类级别的,而不是实例级别的变量(尽管在运行时已经是这种情况):

class MyEnum(int, Enum):
    item1: ClassVar = 0
    item2: ClassVar = 1

    # Other members do not need ClassVar
    other_item_not_in_protocol = 2 

这就是第三个要求的来源:Pyright 通过了这个,但 mypy 没有

我不确定哪一个是正确的。虽然规范确实规定

ClassVar
是区分类级和实例级属性所必需的,但没有任何地方说
Protocol
内定义的实例级属性必须由单个特定类的所有实例共享该类的实例被认为与相关的
Protocol
兼容。

我可能是错的。这是我检查过的所有页面:

© www.soinside.com 2019 - 2024. All rights reserved.