我(练习)试图创建一个使用罗马数字的课程。我试图将尽可能多的功能放入其中,因此我考虑让运营商对它们进行处理。我发现(例如,问题在其他方法对中持续存在)__add__
和__radd__
。文档说明如果__add__
未定义(或者如果失败),则会查看__radd__
,但当我尝试删除__add__
并编辑__radd__
方法时,它会正常工作在0 + myobject
,但不在object1 + object2
上。
以下是课程(因为它们对我的问题不重要,所以会删除一些内容):
class Roman:
num_map = [('M', 1000), ('CM', 900), ('D', 500), ('CD', 400), ('C', 100), ('XC', 90), ('L', 50), ('XL', 40), ('X', 10), ('IX', 9), ('V', 5), ('IV', 4), ('I', 1)]
def __init__(self, num=None):
self.decimal = 0
self.roman = 'N'
if type(num) == type(0):
self.__setattr__('decimal', num)
elif type(num) == type(''):
self.__setattr__('roman', num)
def __setattr__(self, field, value):
if field == 'decimal' and type(value) == type(0):
super().__setattr__('decimal', value)
super().__setattr__('roman', self.dec2roman(value))
elif field == 'roman' and type(value) == type(''):
super().__setattr__('roman', value)
super().__setattr__('decimal', self.roman2dec(value))
方法self.dec2roman(integer)
和self.roman2dec(string)
只是从一种格式转换为另一种格式。
现在,如果我尝试像这样__radd__
:
def __radd__(self, other):
if other == 0:
return self
return Roman(self.decimal + other.decimal)
它不起作用,但这样做:
def __add__(self,other):
return Roman(self.decimal + other.decimal)
def __radd__(self, other):
if other == 0:
return self
return self + other
这是我得到的错误:
>>> from roman import Roman
>>> a = Roman(3)
>>> b = Roman('X')
>>> a + b
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +: 'Roman' and 'Roman'
有人知道发生了什么事吗?
答案 0 :(得分:2)
根据Python文档的the “data model” section,
仅当左操作数不支持相应的操作并且操作数具有不同类型时,才会调用[
__radd__
和类似函数]。
(强调补充。)这就是定义__radd__
不适合你的原因:你试图添加相同类的两个项目。我不确定你为什么试图避免__add__
,但这种方法显然是在这种情况下要求的。
答案 1 :(得分:1)
仅当您的对象是右手操作数时才调用__radd__()
方法。您只需打印整数项的__doc__
即可看到这一点:
In [4]: (1).__radd__.__doc__
Out[4]: 'Return value+self.'
您可以使用示例检查此行为:
In [7]: class A:
...: def __radd__(self, other):
...: return 10
...:
In [8]: a = A()
In [9]: a + 2
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-9-429dec850246> in <module>()
----> 1 a + 2
TypeError: unsupported operand type(s) for +: 'A' and 'int'
In [10]: 2 + a
Out[10]: 10
但是当你使用其中两个对象时,python会调用第一个对象__add__
方法,这就是它引发异常的原因。如果你想获得它,你可以简单地处理__add__
方法中的问题,而不是为它编写逻辑代码。
例如,您可以使用other
作为右手操作数,以便使用__radd__
中的__add__
:
In [24]: class A:
def __radd__(self, other):
return 10
def __add__(self, other):
return 5 + other
....:
In [25]: a = A()
In [26]: a + 2
Out[26]: 7
In [27]: 2 + a
Out[27]: 10
In [28]: a + a
Out[28]: 10