0

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?

zeycus
  • 860
  • 1
  • 8
  • 20

3 Answers3

2

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)
szymanskilukasz
  • 463
  • 3
  • 13
  • thanks, it is simple and works. Although I will try to use Jamie's solution, as an excuse to go deeper into metaprogramming. – zeycus Jul 22 '14 at 16:05
1

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
Jamie Cockburn
  • 7,379
  • 1
  • 24
  • 37
0

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
Ivaylo Petrov
  • 1,162
  • 9
  • 18
  • In fact the class attribute shared by all IS as reference to an instance of a Class. What I wanted was to ensure that it is always shared and no two instances of Class are created. First I though I should use the singleton pattern, but the fact is that in other contexts I want to have the possibility of creating several instances of Class. But anyway maybe you are right and I should rethink the design. – zeycus Jul 22 '14 at 16:09
  • Do you need to change the attribute from the child class? You can have it only in the base class and change it from there. Using inheritance you will break one of the [SOLID](http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)) principles - [Liskov substitution principle](http://en.wikipedia.org/wiki/Liskov_substitution_principle). At least it seems to me that this will be the case... – Ivaylo Petrov Jul 22 '14 at 16:17
  • When the script starts, the attribute is None. Any subclass may need to create it, and once this is done, I want it available for every other subclass. It is not necessary to change it anymore. – zeycus Jul 23 '14 at 07:17