2013-11-01 56 views
7

以下,base_id_id是一个类变量,并在所有子类中共享。
有没有办法将他们分成每个班级?覆盖python中的类变量?

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 
+0

为什么要百位数字代表班级,有什么特别的理由吗?如果你得到100多个实例呢?那么你会有重叠。你会在哪里看到ID,并且有没有比使用ID更好地区分类的方法? (也许你可以显示一些额外的信息,例如。) – jpmc26

+1

这实际上并不重要;即使eugene将ID改为2元组(例如(1,0),(1,1),(1,2)...代表'Child1'),创建独立计数器的问题仍然存在。 –

回答

3

如果你不想违背DRY原则喜欢falsetru建议,你需要使用元类。我正在考虑写点东西,但there's already a good long description of metaclasses on SO,所以检查出来。

总之,元类可以让您控制子类的创建。

基本上,您需要做的是在创建Parent的子类时,将_id成员添加到新创建的子类中。

2

正如您在问题中所述,_id由父级和所有子级共享。为每个儿童班级定义_id

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

使用元类:

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) 
4

如果你真的需要使用ID这种方式,使用参数:

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 

这是假设你将不会被构建的Parent直接实例,但是这看起来合理搭配你的示例代码。