使Python中的@property支持+=、-=等操作
从Python文档中,我看到你可以设置一些方法来处理属性,这样做是很方便的:
class C(object):
def __init__(self):
self._x = None
def getx(self):
return self._x
def setx(self, value):
self._x = value
def delx(self):
del self._x
x = property(getx, setx, delx, "I'm the 'x' property.")
现在假设 C._x
是一个列表。在初始化的时候,它被简单地设置为 []
。所以如果我这样做:
c = C()
c.x = [1,2,3]
c.x
会被设置为 [1,2,3]
。我现在想要做的是
#...
c.x += 4
这样 c.x
现在变成了 [1,2,3,4]
。这个例子很简单,但显然,我希望 setx
和 getx
方法能包含一些处理和检查。否则,使用这种方法就没什么意义了。
编辑: 可能只用 __add__
方法在 C
上来强制执行这种行为就足够了,但我在想是否可以把这种行为放在属性上,而不是整个类上。
3 个回答
0
这是一种可能的解决方案。你可以调整一下 __iadd__
方法的行为。
class C(object):
def __init__(self):
# instanciate an empty list of your custom list-type
self._x = MyList([])
def getx(self):
return self._x
def setx(self, value):
self._x = value
def delx(self):
del self._x
x = property(getx, setx, delx, "I'm the 'x' property.")
class MyList(list):
def __iadd__(self,x):
# if the item is an iterable, extend the list (standard __iadd__ behaviour)
if hasattr(x,"__iter__"):
return super(MyList,self).__iadd__(x)
#if the item is not iterable, append it
else:
return super(MyList,self).__iadd__([x])
用法如下:
>>> c=C()
>>> c.x+=1
>>> c.x
[1]
>>> c.x+="test"
>>> c.x
[1,"test"]
>>> c.x+=[3,4]
>>> c.x
[1,"test",3,4]
总结一下:你不能在 C
的 setitem 方法里重载运算符,因为增加操作并不是在属性上进行的,而是在底层的列表上进行的(因为你的属性只是一个指向那个列表对象的变量)。你可以看看我的评论和其他的回答。
2
不,这样做不行。
基本上,事情是这样的:
c.x += 4
这段代码和下面这段是一样的:
var temp = c.x
temp += 4
c.x = temp
不过,这里的 temp
会是一个包含3个值的列表,而这段代码是不能工作的:
temp = [1, 2, 3]
temp += 4
你会得到:
类型错误:'int'对象不可迭代
所以这和属性没有关系,完全是因为代码需要像这样写:
temp += [4]
这样就可以工作:
c.x += [4]
而这个不能:
c.x += 4
5
你不能为特定的属性重载运算符,因为:
c.x += 4
# is equivalent to
c.x.__iadd__(4)
实际上,你是在调用列表的 __iadd__
运算符。如果你想要实现这个功能,你需要创建一个新的类,继承自列表,并重载 __iadd__
或 __add__
运算符。
class SuperList(list):
def __iadd__(self, other):
if type(other) == list or type(other) == SuperList:
return super(SuperList, self).__iadd__(other)
return super(SuperList, self).__iadd__([other])