我正在处理一个类,我必须实现算术运算符(+
,-
,*
,/
),其中每个运算符都有多个重载,但重载都是相同的。我想我应该将其实现为数据模型对象,而不是将重载复制到每个运算符,沿着这样的路线:
from typing import Callable as Fn, Any, overload
import operator
class Apply:
"""Apply an operator to an object."""
def __init__(self, op: Fn[[Any, Any], Any], obj: Any) -> None:
self.op = op
self.obj = obj
# Two mock overloads...
@overload
def __call__(self, x: int) -> str: ...
@overload
def __call__(self, x: str) -> int: ...
def __call__(self, x: int | str) -> str | int:
...
class Op:
"""Data model object for an operator."""
def __init__(self, op: Fn[[Any, Any], Any]) -> None:
self.op = op
def __get__(self, obj: Any, _: Any) -> Apply:
return Apply(self.op, obj)
class Foo:
__add__ = Op(operator.add)
__mul__ = Op(operator.mul)
foo = Foo()
a: str = foo.__add__(2) # works fine
b: int = foo.__mul__("2") # works fine
_ = foo + 1 # type error
_ = foo * "2" # type error
字符串
这个想法是让所有的操作符重载实现一次,并将动态行为分派到operator
。这样,我就避免了样板代码的多个副本,并且我仍然可以获得所有带有重载类型注解的操作符。
但最后两行给予我类型错误,当我检查与pyright(playground).它似乎是工作与mypy,但我使用pylance+pyright为我的项目,宁愿不改变类型检查.
有没有办法让派莱特也能接受?
1条答案
按热度按时间nzrxty8p1#
看起来pyright只需要一点额外的帮助(参见Pyright playground):
个字符