Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

make python @property handle +=, -= etc

from the Python documentation, I see that you can set methods for handling properties transparently:

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.")

Now assume that C._x is a list. In init it is simply set to []. So if I do the following:

c = C()
c.x = [1,2,3]

c.x will be set to [1,2,3]. What I want to be able to do now is

#...
c.x += 4

So that c.x is now [1,2,3,4]. The example is trivial, but obviously, I'd want the setx and getx methods to include some sort of processing and checks. Otherwise, using this approach would be silly.

Edit: It might be good enough to just use the __add__ method on C to enforce the behaviour, but I wondered if it was possibly to put the behaviour on the property instead of the whole class

like image 985
Eldamir Avatar asked Apr 25 '14 08:04

Eldamir


2 Answers

You can't overload operator for a specific attribute, because :

c.x += 4
# is equivalent to
c.x.__iadd__(4)

So in fact you are calling the __iadd__ operator of list. If you want to be able to do that, you have to create a new class, extending list, and overload operator __iadd__ or __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])
like image 149
Holt Avatar answered Oct 12 '22 22:10

Holt


No, that won't work.

Basically, here's what happens:

c.x += 4

This code is equivalent to this:

var temp = c.x
temp += 4
c.x = temp

However, temp here will be the list of 3 values, and this code doesn't work:

temp = [1, 2, 3]
temp += 4

You get:

TypeError: 'int' object is not iterable

So this has nothing to do with the property, and everything to do with the fact that the code needs to look like this:

temp += [4]

So this works:

c.x += [4]

This cannot:

c.x += 4
like image 30
Lasse V. Karlsen Avatar answered Oct 12 '22 21:10

Lasse V. Karlsen