【问题标题】:Dynamically derive a class in python [duplicate]在python中动态派生一个类[重复]
【发布时间】:2012-08-19 10:01:57
【问题描述】:

可能重复:
Python dynamic inheritance: How to choose base class upon instance creation?

我希望类根据 init 方法中的参数动态选择基类。

Class A():
    #...
Class B():
    #...
Class C():
    def __init__(self, base_type):
        if parent_type == 'A':
            #TODO: make C derive A
        else:
            #TODO: make C derive B

A 和 B 是派生相同基类的库类。

a similar question 的答案看起来太丑了。

【问题讨论】:

  • 你为什么要做这样的事情?尽管在像 python 这样的动态语言中很多事情都是可能的,但这似乎不是一个好的方法。有了更多背景信息,我们或许能够更好地了解您的问题并提供解决方案。
  • 你真的需要使用继承吗?您可以改用组合吗(例如,每个 C 实例都拥有 A 或 B 的实例)?查看您链接的问题的第二个高度评价的答案。
  • 如果您坚持不使用工厂模式,您可能需要研究元类。 docs.python.org/py3k/reference/datamodel.html#metaclasses
  • @cyroxx 我刚刚添加了一个重要细节,即 A 和 B 是派生相同基类的库类。
  • 类似的问题或多或少完全相同,并提供了您将在此处获得的所有答案...如果答案是“丑陋”,您的问题应该解决您认为丑陋的问题这些解决方案,而不仅仅是“给我同一个问题的新答案”。

标签: python inheritance


【解决方案1】:

虽然您可以在__init__ 中更改课程,但在__new__ 中进行更改更合适。前者用于初始化,后者用于构造:

class A(object): pass
class B(object): pass

class C(object):
    def __new__(cls, base_type, *args, **kwargs):
        return super(C, cls).__new__(base_type, *args, **kwargs)

assert isinstance( C(A), A )
assert isinstance( C(B), B )

使用__init__,您正在创建C 的一个实例,然后修改它的类型。使用 __new__,您永远不会创建 C 的实例,只需创建所需的 base_type

【讨论】:

    【解决方案2】:

    我假设您的意思是 base_type 而不是父类型。但以下应该工作

    Class C():
        def __init__(self, base_type):
            if base_type == 'A':
                self.__class__=A
            else:
                self.__class__=B
    

    可以在此处找到有关此方法的更多详细信息:http://harkablog.com/dynamic-state-machines.html

    【讨论】:

    • 否决票的任何原因?
    【解决方案3】:

    我完全同意 cyroxx,你应该给我们一些关于你的问题的背景信息。就目前而言,__init__ 在创建类的实例以初始化其成员之后被调用。更改继承为时已晚。

    一个简单的类工厂对你来说足够了吗:

    class MyA(ABMixin, A): pass
    
    class MyB(ABMixin, B): pass
    
    def factory(class_type):
        if class_type == 'A':
            return MyA()
        else:
            return MyB()
    

    我建议阅读this SO answer 了解python 中的动态类创建。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-19
      • 1970-01-01
      • 2018-08-09
      • 1970-01-01
      • 2013-11-20
      • 2011-12-25
      • 1970-01-01
      • 2014-04-13
      相关资源
      最近更新 更多