2017-07-28 109 views
0

我想創建一個可以繼承對象「A(對象)」或對象「B(對象)」的子類「sub()」。在python中繼承動態對象

這樣做的以下工作:

class A(object): 
    def __init__(self): 
     print "Class A was inherited" 


class B(object): 
    def __init__(self): 
     print "Class B was inherited" 


class sub(A if inh==A else B): 
    def __init__(self,inh): 
     if inh==A: 
      A.__init__(self) 
     else: 
      B.__init__(self) 

然而, 「INH」 是不是我建我的一個定義的參數 「子()」。我希望能夠用一個參數「inh」來構造我的「sub()」,它初始化「A(object)」或「B(object)」。

這樣:

my_object = sub(inh = A) 

會給我:

Class A was inherited 

這:

my_object = sub(inh = B) 

會給我

Class B was inherited 

我的問題是,如何將「inh」傳遞給構造函數「sub()」,以便它可以選擇正確的對象來繼承?

+1

您不能。繼承在創建類型時完成,而不是在實例化時完成。但是,您可以動態創建一個新類。 – spectras

+4

你爲什麼要這樣做?聞起來像[XY問題](https://meta.stackexchange.com/q/66377/322040)。 – ShadowRanger

+0

我想__應該可以使用[metaclass](https://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python)和['__new__'](https:// infohost。 nmt.edu/tcc/help/pubs/python/web/new-new-method.html),但我真的沒有看到任何情況下這是最好的選擇。 – jdehesa

回答

1

在我看來,你想要的是一個生成器/工廠函數,它將構建並返回一個類實例,如你所願。 對於這一點,你可以使用Python來函數中定義類和功能,使您的class sub定義將在工廠功能的範圍來完成,像這樣的能力:

def Sub(inh=object): 
    class sub(inh): 
     def __init__(self): 
      super(sub, self).__init__() 
    return sub() 

您現在可以通過所需子類添加到您的生成器函數中並獲取所需類型的實例化實例。

執行命令輸出:

>>> def Sub(inh=object): 
...  class sub(inh): 
...  def __init__(self): 
...   super(sub, self).__init__() 
...  return sub() 
... 
>>> class A(object): 
...  def __init__(self): 
...   print "Class A was inherited" 
... 
>>> 
>>> class B(object): 
...  def __init__(self): 
...   print "Class B was inherited" 
... 
>>> 
>>> Sub(A) 
Class A was inherited 
<__main__.sub object at 0x014E4970> 
>>> Sub(B) 
Class B was inherited 
<__main__.sub object at 0x014E49F0> 
>>> 

是任意的。

+1

爲什麼輸入(inh)'?如果你傳遞一個類作爲參數,它將使用它的元類作爲基類,這當然不是OP所要求的。 –

+0

你說得對,當我注意到它之前我已經修好了。 – immortal

+3

此外,這將在每次調用時創建一個新的'sub'類,這將在類上進行'isinstance()'測試或身份測試。 –

2

不朽的解決方案,雖然基本上是正確的,但有一個缺點:每個Sub()的電話會產生一個新的類,所以像isinstance()或類身份測試的東西將打破。解決方案是保留已創建類的映射:

_CLSMAP = {} 

def Sub(base, *args, **kw): 
    if base not in _CLSMAP: 
     class Sub(base): 
      def __init__(self, *args, **kw): 
       super(sub, self).__init__(*args, **kw) 
    _CLSMAP[base] = Sub 
    return _CLSMAP[base](*args, **kw)