考虑此类,其中根据某些参数的值添加方法:
class Something(object):
def __init__(self, value, op='+'):
self.x = value
if op == '+':
self.add = self._operator
elif op == '-':
self.sub = self._operator
def _operator(self, other):
return self.x * other
x = Something(10)
x.add(3)
# 30
现在,我想使用+
和-
运算符,而不是.add()
或.sub()
表示法。
为此,我会写:
class Something(object):
def __init__(self, value, op='+'):
self.x = value
if op == '+':
self.__add__ = self._operator
self.__radd__ = self._operator
elif op == '-':
self.__sub__ = self._operator
self.__rsub__ = self._operator
def _operator(self, other):
return self.x * other
x = Something(10)
print(x + 3)
但是我得到的不是30
,
TypeError:+不支持的操作数类型:“ Something”和“ int”
尽管如此:
print(dir(x))
# ['__add__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__radd__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_operator', 'x']
出了什么问题,我该如何解决?
这与Overriding special methods on an instance的不同之处在于,在创建对象后,我不尝试向对象的实例添加特殊方法,即:
x = Something(10)
x.__add__ = ...
但是,在class.__init__()
期间,虽然很公认,错误的来源和解决方案都非常相似。
答案 0 :(得分:1)
特殊方法通常避免使用属性查找机制。他们不检查实例属性,而是直接在类中查找。
3.3.10. Special method lookup
对于自定义类,只有在对对象的类型(而不是在对象的实例字典中)进行定义的情况下,才能保证对特殊方法的隐式调用可以正常工作。
[...]
以这种方式绕过
__getattribute__()
机器为解释器内的速度优化提供了很大的空间,其代价是在处理特殊方法时需要一定的灵活性(必须设置特殊方法 在类对象本身上,以便被解释程序一致地调用。)
但是,您仍然可以使用特殊方法来引用实例属性。
扩展您的示例(可能会有更优雅的方式):
class Something(object):
def __init__(self, value, op='+'):
self.x = value
if op == '+':
self._add = self._operator
self._radd = self._operator
elif op == '-':
self._sub = self._operator
self._rsub = self._operator
def _operator(self, other):
return self.x * other
def __add__(self, other):
try:
return self._add(other)
except AttributeError:
return NotImplemented
# etc. for __radd__, __sub__ and __rsub__
x = Something(10)
print(x + 3)
答案 1 :(得分:0)
好吧,不要太在意,尽您所能,所以只需使用:
class Something(object):
def __init__(self, value):
self.x = value
def __add__(self, other):
return self.x * other
def __sub__(self, other):
return self.x * other
x = Something(10)
print(x + 3)
输出:
30
它也可以与-
一起使用。