【问题标题】:Pass a parent class as an argument?将父类作为参数传递?
【发布时间】:2013-09-12 01:10:03
【问题描述】:

是否可以在创建实例之前不指定父类?
例如像这样:

class SomeParentClass:
    # something

class Child(unspecifiedParentClass):
    # something

instance = Child(SomeParentClass)

这显然行不通。但是有可能以某种方式做到这一点吗?

【问题讨论】:

  • 同时,在这里查看接受的答案:stackoverflow.com/questions/15247075/…
  • 或者,如果不想/需要动态创建类,您可以放弃继承,只需将一些“帮助”实例传递给子构造函数。 Python 的鸭子类型可以满足大多数需求
  • 感谢@septi 这有帮助。
  • 您可以在运行时使用type 创建一个类,但创建一个类并之后修改它的mro 似乎不是一件容易的事,至少不是来自 python 方面(而且,无论如何,设计中有问题,这是一个非常巨大的代码气味)。

标签: python inheritance arguments unspecified


【解决方案1】:

您可以在运行时动态更改基类。如:

class SomeParentClass:
    # something

class Child():
    # something

def change_base_clase(base_class):
    return type('Child', (base_class, object), dict(Child.__dict__))()

instance = change_base_clase(SomeParentClass)

例如:

class Base_1:
    def hello(self):
        print('hello_1')

class Base_2:
    def hello(self):
        print('hello_2')

class Child:pass

def add_base(base):
    return type('Child', (base, object), dict(Child.__dict__))()

# if you want change the Child class, just:
def change_base(base):
    global Child
    Child = type('Child', (base, object), dict(Child.__dict__))

def main():
    c1 = add_base(Base_1)
    c2 = add_base(Base_2)
    c1.hello()
    c2.hello()

main()

结果:

hello_1
hello_2

在 python 2 和 3 中运行良好。

更多信息请查看相关问题How to dynamically change base class of instances at runtime?

【讨论】:

  • 这不会改变原来的基类;它会创建一个同名的新类。
  • 你可以global Child; Child = type('Child', (base, object), dict(Child.__dict__))
【解决方案2】:

你尝试过这样的事情吗?

class SomeParentClass(object):
    # ...
    pass

def Child(parent):
    class Child(parent):
        # ...
        pass

    return Child()

instance = Child(SomeParentClass)

在 Python 2.x 中,还要确保包含 object 作为父类的超类,以使用新样式类。

【讨论】:

  • def Child 返回一个新类,而不是 instance
  • 或者你可以在子函数中返回一个实例:return Child()
【解决方案3】:

你可以在类的__init__()方法中改变一个实例的类:

class Child(object):
    def __init__(self, baseclass):
        self.__class__ = type(self.__class__.__name__,
                              (baseclass, object),
                              dict(self.__class__.__dict__))
        super(self.__class__, self).__init__()
        print 'initializing Child instance'
        # continue with Child class' initialization...

class SomeParentClass(object):
    def __init__(self):
        print 'initializing SomeParentClass instance'
    def hello(self):
        print 'in SomeParentClass.hello()'

c = Child(SomeParentClass)
c.hello()

输出:

initializing SomeParentClass instance
initializing Child instance
in SomeParentClass.hello()

【讨论】:

  • 这是 imo 更好的解决方案。
  • @linxtion 想解释一下为什么?我实际上认为接受的答案更加透明和灵活。
  • 自从 3 年以来,我不太记得这件事了。再看一遍,公认的解决方案更容易阅读,但它与 pep8 背道而驰。真的取决于你。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-22
  • 2012-03-15
  • 2015-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多