Min*_*ark 6 python magic-methods
说我已经建立包含一个库Foo类,与一些魔术方法的支持,说__add__()和__radd__():
>>> class Foo(object):
... def __add__(self, rhs):
... print("Foo.__add__", rhs)
... def __radd__(self, lhs):
... print("Foo.__radd__", lhs)
...
>>> foo = Foo()
>>> foo + 3
Foo.__add__ 3
>>> 3 + foo
Foo.__radd__ 3
Run Code Online (Sandbox Code Playgroud)
在计算时3 + foo,python首先调用type(3).__add__(3, foo),但是当它返回时NotImplemented,它会回退到type(foo).__radd__(foo, 3):
>>> type(3).__add__(3, foo)
NotImplemented
Run Code Online (Sandbox Code Playgroud)
我希望开发人员能够在我的库之上构建库,比如一个包含类的库Bar,我希望它们能够完全控制.特别是,我想实现一些机制,让其他库决定是否foo + bar应该调用foo.__add__(bar)或bar.__radd__(foo).
我看到NumPy使用该__array_priority__方案解决了这个问题.但这似乎引起了一些令人头疼的问题(考虑到问题和问题的数量).还有其他最佳做法吗?
一种流行的选择是维护 LHS 支持的类型列表,如果 RHS 的类型不在列表中,则返回NotImplemented:
class Foo(object):
SUPPORTED_TYPES = (int, Foo)
def __add__(self, rhs):
if isinstance(type(rhs), SUPPORTED_TYPES):
[...] # compute self + rhs
else:
return NotImplemented
Run Code Online (Sandbox Code Playgroud)
这很有效,除非rhs它是其中之一的智能子类型SUPPORTED_TYPES:它无法获得控制。而且,这种方式列出类型不是很灵活。依赖鸭子类型可能比依赖硬编码类型列表更好。