0

I have a python class A with attribute instance_b as follows :

class A(object):

    instance_b = 0

    def getB(self):
        # Do something Fancy here
        return self.instance_b

    def setB(self, value):
        # Do something Fancy here
        self.instance_B = value

    b = property(getB, setB)

The property() function allows me to specify a getter and setter. But is there a way I can specify an incrementer and decrementer? Can I specify similar methods for other operations?

More importantly to me, what if instance_b is a list instead of an integer. Can I set methods that will substitute for ".insert()" and "+=" and "[-1]"?

Or are only getters and setters (and deletes) allowed to be specified..... And I have to use them to do what I need. So adding an element to the list instance_b would need to look something like this?

a = A()
a.b = a.b + ["my_item"]
martineau
  • 119,623
  • 25
  • 170
  • 301
Saqib Ali
  • 11,931
  • 41
  • 133
  • 272

2 Answers2

0

"if instance_b is a list instead of an integer" you could perfectly well call list methods on it after getB returns it. If you need to intercept some list methods (or operators, &c), then you need to return the list wrapped into a class of your own that does the interception.

So the simple case might be...:

class A(object):

    instance_b = []

    def getB(self):
        # Do something Fancy here
        return self.instance_b

    def setB(self, value):
        # Do something Fancy here
        self.instance_B = value

    b = property(getB, setB)

Now for example:

a = A()
a.b.append(23)
print(a.b)

displays [23] as expected.

Now supposed that for devious reasons of your own you want append on a.b to act twice (while other list methods work normally, and you don't care about operators). This requires a simple wrapper class:

class Double(object):
    def __init__(self, alist):
        self.alist = alist

    def append(self, v):
        self.alist.extend((v,v))

    def getattr(self, n):
        return getattr(self.alist, n)

    def __str__(self):
        return str(self.alist)

and changing your getB to return Doubt(self.instance_B). Now, the same code as before displays [23, 23] -- again as expected.

Intercepting operators is also quite possible, just a bit more laborious, and I'll leave that as an exercise to the interested reader:-).

Alex Martelli
  • 854,459
  • 170
  • 1,222
  • 1,395
0

If you fix the bug in your code, then the property function with basic getter and setter methods like that will allow you to do everything you mentioned:

class A(object):

    instance_b = 0

    def getB(self):
        # Do something Fancy here
        return self.instance_b

    def setB(self, value):
        # Do something Fancy here
        self.instance_b = value  # <-- this line in your code was wrong

    b = property(getB, setB)

a = A()
print(a.b)               # --> 0
a.b += 42
print(a.b)               # --> 42
a.b = []                 # replace with an empty list
print(a.b)               # --> []
a.b = a.b + ["my_item"]
print(a.b)               # --> ['my_item']
a.b.insert(0, 23)
print(a.b)               # --> [23, 'my_item']
print(a.b[-1])           # --> my_item
martineau
  • 119,623
  • 25
  • 170
  • 301