假设我想在集合和列表上定义包装类,以添加一些有用的方法,如下所示:
from abc import ABC
class AbstractGizmo(ABC):
def bloviate(self):
print(f"Let me tell you more about my {len(self)} elements")
class ListGizmo(list, AbstractGizmo):
pass
class SetGizmo(set, AbstractGizmo):
pass
现在我可以打电话了:
>>> ListGizmo([1, 2, 3]).bloviate()
>>> SetGizmo({1, 2, 3}).bloviate()
但我也想拥有bloviate()
自己的实用方法:
from typing import Union, Set, List
def bloviate(collection: Union[Set, List]):
print(f"Let me tell you more about my {len(collection)} elements")
class AbstractGizmo(ABC):
def bloviate(self):
return bloviate(self)
所以我也可以这样做:
>>> bloviate([1, 2, 3])
>>> bloviate({1, 2, 3})
由于 subclassListGizmo
是一个列表,而 subclassSetGizmo
是一个集合,所以这个设置在实践中实际上工作得很好。但是静态类型检查器(如 pyright)不知道,所以它们(正确地)在这里显示错误:
class AbstractGizmo(ABC):
def bloviate(self):
return bloviate(self) # Error: Type 'AbstractGizmo' cannot be assigned
# to type 'Set[Unknown] | List[Unknown]'
有什么方法可以向 Python / pyright 表明,基本上,“所有实例AbstractGizmo
都保证在Union[Set, List]
”?这种语法逃脱了我。
(注意,当然在这个简单的例子中,我可以只定义bloviate()
每个子类来避免这个问题。实际上我有更多的方法和更多的包装子类,所以如果我不能将它们抽象为AbstractGizmo
.)