Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Object Property Sharing

I have a class that keeps track of several other classes. Each of these other classes all need to access the value of a particular variable, and any one of these other classes must also be able to modify this particular variable such that all other classes can see the changed variable.

I tried to accomplish this using properties. An example is as follows:

class A:
    def __init__(self, state):
        self._b_obj = B(self)
        self._state = state

    @property
    def state(self):
        return self._state

    @state.setter
    def state(self,val):
        self._state = val

    @property
    def b_obj(self):
        return self._b_obj

    @b_obj.setter
    def b_obj(self,val):
        self._b_obj = val


class B:
    def __init__(self, a_obj):
        self.a_obj = a_obj

    @property
    def state(self):
        return self.a_obj.state

    @state.setter
    def state(self,val):
        self.a_obj.state = val

I want it to work as follows:

>>> objA = A(4)
>>> objB = objA.b_obj
>>> print objA.state
4
>>> print objB.state
4
>>> objA.state = 10
>>> print objA.state
10
>>> print objB.state
10
>>> objB.state = 1
>>> print objA.state
1
>>> print objB.state
1

Everything works as I want it to except for the last 3 commands. They give:

>>> objB.state = 1
>>> print objA.state
10
>>> print objB.state
1

Why do the last 3 commands return these values? How can I fix this so that they return the desired values?

Thanks

like image 358
Bedlington Avatar asked Feb 25 '16 18:02

Bedlington


1 Answers

So it seems all you needed to do is have your classes inherit from object :-) That gives you new-style classes and all their benefits.

class A(object):
    ...  # rest is as per your code

class B(object):
    ...  # rest is as per your code

>>> objA = A(4)
>>> objB = objA.b_obj
>>> print objA.state
4
>>> print objB.state
4
>>> objA.state = 10
>>> print objA.state
10
>>> print objB.state
10
>>> objB.state = 1
>>> print objA.state
1
>>> print objB.state
1

The specific reasons for why this would work only with new-style classes, from here:

For objects, the machinery is in object.__getattribute__() which transforms b.x into type(b).__dict__['x'].__get__(b, type(b)).

For classes, the machinery is in type.__getattribute__() which transforms B.x into B.__dict__['x'].__get__(None, B).

(from "important points to remember")

  • __getattribute__() is only available with new style classes and objects

  • object.__getattribute__() and type.__getattribute__() make different calls to __get__().

like image 118
aneroid Avatar answered Oct 04 '22 05:10

aneroid