当我定义带有泛型类型参数的类型时(例如
K
/
V
映射的键和值),我似乎无法编写合适的
isinstance
检查来实现
__eq__
:
from collections import OrderedDict
from collections.abc import MutableMapping
from typing import TypeVar
K = TypeVar("K")
V = TypeVar("V")
class MyDictWrapper(MutableMapping[K, V]):
def __init__(self):
self.cache: OrderedDict[K, V] = OrderedDict()
def __eq__(self, other: object) -> bool:
if not isinstance(other, MyDictWrapper):
return NotImplemented
return self.cache == other.cache # Pyright error: Type of "cache" is partially unknown: Type of "cache" is "OrderedDict[Unknown, Unknown]
(这是关于
pyright 1.1.309
,请参阅
Pyright Playground 重现
)
替代方案
if not isinstance(other, MyDictWrapper[K, V]):
也不起作用,错误如下:
Second argument to "isinstance" must be a class or tuple of classes
Generic type with type arguments not allowed for instance or class
是否有正确的方法来输入此内容?
你不能用
isinstance
来检查类型参数,Python 中的泛型主要在运行时被删除。但是,你可以通过以下方式解决这个问题:
-
鸭子类型:
不要显式检查类型,而是检查所需的行为。在你的情况下,这意味着检查
other
对象是否具有一个名为cache
的属性,并且该属性的行为像一个OrderedDict
:
from collections import OrderedDict
from collections.abc import MutableMapping
from typing import TypeVar
K = TypeVar("K")
V = TypeVar("V")
class MyDictWrapper(MutableMapping[K, V]):
def __init__(self):
self.cache: OrderedDict[K, V] = OrderedDict()
def __eq__(self, other: object) -> bool:
if not hasattr(other, "cache"):
return NotImplemented
# 检查 other.cache 是否是 OrderedDict 或具有相同接口的对象
try:
return self.cache == other.cache
except TypeError:
return False
-
使用
typing.Protocol
(Python 3.8+): 你可以定义一个协议来描述你期望的行为,然后使用isinstance
来检查它。这在运行时仍然不起作用,但它可以帮助类型检查器理解你的意图:
from collections import OrderedDict
from collections.abc import MutableMapping
from typing import TypeVar, Protocol
K = TypeVar("K")
V = TypeVar("V")
class Cacheable(Protocol):
cache: OrderedDict
class MyDictWrapper(MutableMapping[K, V]):
def __init__(self):
self.cache: OrderedDict[K, V] = OrderedDict()
def __eq__(self, other: object) -> bool:
if not isinstance(other, Cacheable):
return NotImplemented
return self.cache == other.cache
请记住,这两种方法主要用于类型检查。在运行时,Python 不会强制执行泛型类型参数,因此你仍然需要小心处理潜在的类型错误。
标签:python,python-typing,pyright From: 77923461