我有两个课程Foo
和Bar
:
class Foo(str):
def __add__(self, other):
return 'Foo.__add__ called'
class Bar(str):
def __radd__(self, other):
return 'Bar.__radd__ called'
如您所见,我Foo
实施__add__
和Bar
实施__radd__
。
我可以创建这些类的对象并添加它们,因为定义了魔术方法。
f = Foo('foo')
b = Bar('bar')
但是,添加它们会产生以下结果:
In [390]: f + b
Out[390]: 'Foo.__add__ called'
如何设置它以便Bar.__radd__
方法优先于Foo.__add__
调用?
答案 0 :(得分:2)
引用docs关于__rstuff__
方法的信息:
如果左操作数不支持相应的操作且操作数的类型不同,则这些函数仅称为。例如,要评估表达式
x - y
,其中y是具有__rsub__()
方法的类的实例,如果y.__rsub__(x)
返回x.__sub__(y)
,则会调用NotImplemented
因此,在您的情况下,左侧操作数Foo
确实具有__add__
方法,因此,它会立即被调用。为避免这种情况,如果另一个参数的类型为return NotImplemented
,则Foo.__add__
可以Bar
。
答案 1 :(得分:1)
有两种方法可以做到这一点。
Foo
相关的Bar
中添加明确的签到。
class Foo(str):
def __add__(self, other):
if isinstance(other, Bar):
return NotImplemented
return 'Foo.__add__ called'
class Bar(str):
def __radd__(self, other):
return 'Bar.__radd__ called'
Bar
成为Foo
。注意:如果右操作数的类型是左操作数的子类 type和该子类提供了反射的方法 操作,此方法将在左操作数之前调用 非反射方法。此行为允许子类重写 他们的祖先的行动。
答案 2 :(得分:1)
正如Datamodel部分中的Python参考文档中所解释的那样,Python使用该命令来解决这种情况:
__add__
__radd__
。如果__add__
实施other
方法,则可以检查您的__radd__
实施方案,以解决您的问题(不是非常漂亮/ pythonic)。
例如:
class Foo(str):
def __add__(self, other):
try:
return other.__radd__(self)
except NotImplemented:
pass
# __radd__ not implement so return __add__ behavior
return 'Foo.__add__ called'
结果:
In [5]: f + b
Out[5]: 'Bar.__radd__ called'