2012-09-19 74 views
3

我提出這是使用類Python程序,我想一個類僅選擇從另一個e.g繼承:選擇性繼承的Python

class X(object): 
    def __init__(self): 
     self.hello = 'hello' 

class Y(object): 
    def __init__(self): 
     self.moo = 'moo' 

class Z(): 
    def __init__(self, mode): 
     if mode == 'Y': 
      # Class will now Inherit from Y 
     elif mode == 'X': 
      # Class will now Inherit for X 

我怎麼能做到這一點而不進行其他類?

+2

能否請您給,爲什麼你希望它是這樣一點點更多信息?考慮到這些事實,作爲一個設計決策,我似乎有點奇怪。 – StoryTeller

回答

0

我想你最好在Z中定義兩個成員,一個是X的類實例,另一個是Y的實例。在使用不同模式時,可以獲得存儲在這些實例中的關聯信息。

+0

他想要兩個不同的類,而不是兩個不同的實例。我不明白你提出的解決方案會有什麼用處。 – l4mpi

3

在Python類可以在運行時創建:

class X(object): 
    def __init__(self): 
     self.hello = 'hello' 

class Y(object): 
    def __init__(self): 
     self.moo = 'moo' 

def create_class_Z(mode): 
    base_class = globals()[mode] 
    class Z(base_class): 
     def __init__(self): 
      base_class.__init__(self) 
    return Z 

ZX = create_class_Z('X') 
zx = ZX() 
print(zx.hello) 

ZY = create_class_Z('Y') 
zy = ZY() 
print(zy.moo) 
2

您可以通過overriding __new__併爲此改變cls通過附加XY作爲基地(您正在創建一個新的類型傳遞類):

class X(object): 
    def __init__(self): 
     self.hello = 'hello' 

class Y(object): 
    def __init__(self): 
     self.moo = 'moo' 

class Z(object): 
    def __new__(cls, mode): 
     mixin = {'X': X, 'Y': Y}[mode] 
     cls = type(cls.__name__ + '+' + mixin.__name__, (cls, mixin), {}) 
     return super(Z, cls).__new__(cls) 
    def __init__(self, mode, *args, **kwargs): 
     super(Z, self).__init__(*args, **kwargs) 

請注意,您需要使用super避免無限遞歸繞過Z.__new__;這是__new__特殊覆蓋方法的標準模式。

+1

我認爲這個解決方案與在Z類以外的函數中創建新類型相比過於複雜,避免了無限遞歸陷阱...... – l4mpi

+1

@ l4mpi它幾乎不是一個陷阱;這是標準的成語。編寫'__new__'的優點是將相關代碼保存在一起並保持與現有代碼的兼容性。 – ecatmur

+0

編寫另一個函數的優點是能夠重用它 - 我的解決方案被硬編碼爲使用類Z作爲第一個基類,但是您可以將它放入帶有類和基類映射的閉包中,並將其用於多個班級。這樣做意味着你要以這種方式爲每個類添加大約兩行代碼 - 不應該太難以與代碼的其餘部分保持一致。另外,你能否詳細說明兼容性部分? – l4mpi

0

使用type A液:

class _Z(): pass #rename your class Z to this 

def Z(mode): #this function acts as the constructor for class Z 
    classes = {'X': X, 'Y': Y, 'Foo': Bar} #map the mode argument to the base cls 
    #create a new type with base classes Z and the class determined by mode 
    cls = type('Z', (_Z, classes[mode]), {}) 
    #instantiate the class and return the instance 
    return cls() 
+0

這失敗了'isinstance(Z('X'),Z)'。 – ecatmur

+0

@ecatmur是的,但你不應該使用isinstance反正:http://www.canonical.org/~kragen/isinstance/ – l4mpi

+0

這是過時的; Python現在有ABC和虛擬接口。 – ecatmur