2013-11-01 96 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直接實例,但是這看起來合理搭配你的示例代碼。