2017-07-28 108 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)