Below, base_id
and _id
is a class variable and shared among all child classes.
Is there a way to separate them into each class?
If you don't want to violate the DRY principle like falsetru suggests, you'll need to use metaclasses. I was thinking of writing something up, but there's already a good long description of metaclasses on SO, so check it out.
Metaclasses, in short, let you control subclass creation.
Basically, what you need to do is, upon the creation of a subclass of Parent
, add the _id
member to the newly-created subclass.
As you said in the question, _id
is shared by parent and all children classes. Define _id
for every children classes.
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 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)
If you really need to use the ID this way, use parameters:
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
etc.
This assumes you won't be constructing instances of Parent
directly, but that looks reasonable with your example code.