如果您已经
my_average(a, b)按照
add和
div功能实现了,例如:
def my_average(a, b): return div(add(a, b), 2)
然后为不同的类型提供不同的实现,可以使用
functools.singledispatch:
import functools@singledispatchdef div(x, y:int): # default implementation raise NotImplementedError('for type: {}'.format(type(x)))@div.register(Divisible) # anything with __truediv__ methoddef _(x, y): return x / y@singledispatchdef add(a, b): raise NotImplementedError('for type: {}'.format(type(a)))@add.register(Addable) # anything with __add__ methoddef _(a, b): return a + b
其中
Addable,
Divisable可以定义为:
例from abc import ABCmeta, abstractmethodclass Divisible(metaclass=ABCmeta): """Anything with __truediv__ method.""" __slots__ = () __hash__ = None # disable default hashing @abstractmethod def __truediv__(self, other): """Return self / other.""" @classmethod def __subclasshook__(cls, C): if cls is Divisible: if any("__truediv__" in B.__dict__ for B in C.__mro__): return True return NotImplementedclass Addable(metaclass=ABCmeta): """Anything with __add__ method.""" __slots__ = () __hash__ = None # disable default hashing @abstractmethod def __add__(self, other): """Return self + other.""" @classmethod def __subclasshook__(cls, C): if cls is Addable: if any("__add__" in B.__dict__ for B in C.__mro__): return True return NotImplemented
>>> isinstance(1, Addable) # has __add__ methodTrue>>> isinstance(1, Divisible) # has __truediv__ methodTrue>>> my_average(1, 2)1.5>>> class A:... def __radd__(self, other):... return D(other + 1)...>>> isinstance(A(), Addable)False>>> _ = Addable.register(A) # register explicitly>>> isinstance(A(), Addable)True>>> class D:... def __init__(self, number):... self.number = number... def __truediv__(self, other): ... return self.number / other...>>> isinstance(D(1), Divisible) # via issubclass hookTrue>>> my_average(1, A())1.0>>> my_average(A(), 1) # no A.__div__Traceback (most recent call last):...TypeError: unsupported operand type(s) for +: 'A' and 'int'
内置数字,例如
intdefine
__add__,
__truediv__method,因此它们自动得到支持。如类
A所示,即使它们没有定义特定的方法,也可以使用类,例如,如果仍然可以在给定的实现中使用它们,则可以通过显式
__add__调用
.register方法。
如有必要,使用
add.register和
div.register定义其他类型的实现,例如:
@div.register(str)def _(x, y): return x % y
之后:
>>> my_average("%s", "b") # -> `("%s" + "b") % 2`'2b'
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)