zeycus
zeycus

Reputation: 890

Share class attributes among several classes in Python

I have a class that contains class attributes. I need that they are shared as class attributes by a group of other classes, so that if any of them modifies those attributes, they are modified for all of them. I naively tried it using inheritance, but it is not working like that: each class behaves as if it would have their own "copy" of those class attributes.

Files:

# baseClass.py 
class BaseClass(object):
    iden = 0


# child1.py 
from baseClass import BaseClass

class Child1(BaseClass):
    @classmethod
    def getId(cls):
        return cls.iden


# child2.py
from baseClass import BaseClass

class Child2(BaseClass):
    @classmethod
    def getId(cls):
        return cls.iden

The file I am using to test this is:

from child1 import Child1
from child2 import Child2

print(Child1.getId()) 
Child1.iden = 5
print(Child1.getId())
print(Child2.getId())

The output I am seeing:

0
5
0

How should I do this, so that Child1, Child2 and BaseClass share the iden class attribute?

Upvotes: 0

Views: 153

Answers (3)

Ivaylo Petrov
Ivaylo Petrov

Reputation: 1172

I would not use inheritance. If you really need to change the attribute from the Child1 and Child2 you can also use __setattr__ and change the attribute of the base class. I would not recommend that though... It seems to me that there is some problem in the design. Why do you need to change the attribute from the children? Maybe you want to add a new class that holds this property and all the other classes will have a reference to it?

As far as I understood, the following should work just fine for your case:

# baseClass.py 
class BaseClass(object):

    def initializeIden():
        # Do some initialization
        BaseClass.iden = 0


# child1.py 
from baseClass import BaseClass

class Child1:
    @classmethod
    def getId(self):
        if not hasattr(BaseClass, "iden"):
            BaseClass.initializeIden()
        return BaseClass.iden


# child2.py
from baseClass import BaseClass

class Child2(BaseClass):
    @classmethod
    def getId(self):
        if not hasattr(BaseClass, "iden"):
            BaseClass.initializeIden()
        return BaseClass.iden

Upvotes: 0

Jamie Cockburn
Jamie Cockburn

Reputation: 7555

You can do this by adding an iden property to the metaclass of BaseClass:

class BaseType(type):
    _iden = 0
    def _get_iden(cls):
        return BaseType._iden
    def _set_iden(cls, value):
        BaseType._iden = value
    iden = property(_get_iden, _set_iden)

class BaseClass(object):
    __metaclass__ = BaseType

class Child1(BaseClass):
    pass

class Child2(BaseClass):
    pass

print Child1.iden
Child1.iden = 5
print Child1.iden
print Child2.iden

Output:

0
5
5

Upvotes: 1

szymanskilukasz
szymanskilukasz

Reputation: 491

Try this:

# baseClass.py 
class BaseClass(object):
    iden = 0
    @classmethod
    def set_id(cls, id):
        BaseClass.iden = id

You can call it like:

Child1.set_id(5)

Upvotes: 2

Related Questions