Override class variable in python?

Below base_id and _id is a class variable and is used for all child classes. Is there a way to divide them into each class?

 from itertools import count class Parent(object): base_id = 0 _id = count(0) def __init__(self): self.id = self.base_id + self._id.next() class Child1(Parent): base_id = 100 def __init__(self): Parent.__init__(self) print 'Child1:', self.id class Child2(Parent): base_id = 200 def __init__(self): Parent.__init__(self) print 'Child2:', self.id c1 = Child1() # 100 c2 = Child2() # 201 <- want this to be 200 c1 = Child1() # 102 <- want this to be 101 c2 = Child2() # 203 <- want this to be 201 
+7
python class
source share
3 answers

If you do not want to violate the DRY principle, as falsetru suggests, you will need to use metaclasses. I was thinking of writing something, but there is already a good long description of metaclasses in SO , so check it out.

Metaclasses, in short, allow you to control the creation of a subclass.

Basically, what you need to do is, after subclassing the Parent add the _id element to the newly created subclass.

+3
source share

If you really need to use the identifier this way, use the options:

 class Parent(object): def __init__(self, id): self.id = id class Child1(Parent): _id_counter = count(0) def __init__(self): Parent.__init__(self, 100 + self._id_counter.next()) print 'Child1:', self.id 

and etc.

It is assumed that you will not directly create Parent instances, but that looks reasonable with your sample code.

+4
source share

As you said in the question, _id is shared by the parent and all child classes. Define _id for each child class.

 from itertools import count class Parent(object): base_id = 0 _id = count(0) def __init__(self): self.id = self.base_id + self._id.next() class Child1(Parent): base_id = 100 _id = count(0) # <------- def __init__(self): Parent.__init__(self) print 'Child1:', self.id class Child2(Parent): base_id = 200 _id = count(0) # <------- def __init__(self): Parent.__init__(self) print 'Child2:', self.id c1 = Child1() # 100 c2 = Child2() # 200 c1 = Child1() # 101 c2 = Child2() # 201 

UPDATE

Using the metaclass:

 class IdGenerator(type): def __new__(mcs, name, bases, attrs): attrs['_id'] = count(0) return type.__new__(mcs, name, bases, attrs) class Parent(object): __metaclass__ = IdGenerator base_id = 0 def __init__(self): self.id = self.base_id + next(self._id) 
+2
source share

All Articles