【问题标题】:python: multiple inheritance and __add__() in base classpython:基类中的多重继承和__add__()
【发布时间】:2011-04-13 07:00:54
【问题描述】:

我有一个基类,我想在其中处理 __add__() 并希望在 __add__ 处理两个子类实例时支持 - 即在结果实例中具有两个子类的方法。

import copy

class Base(dict):
    def __init__(self, **data):
        self.update(data)

    def __add__(self, other):
        result = copy.deepcopy(self)
        result.update(other)
        # how do I now join the methods?
        return result

class A(Base):
    def a(self):
        print "test a"

class B(Base):
    def b(self):
        print "test b"


if __name__ == '__main__':
    a = A(a=1, b=2)
    b = B(c=1)
    c = a + b
    c.b() # should work
    c.a() # should work

编辑:更具体地说:我有一个类Hosts,它拥有一个dict(host01=.., host02=..)(因此是dict 的子类) - 这提供了一些基本方法,例如@ 987654327@

现在我有一个子类HostsLoadbalancer 包含一些特殊方法,例如drain(),我有一个类HostsNagios 包含一些特定于nagios 的方法。

然后我正在做的事情是这样的:

nagios_hosts = nagios.gethosts()
lb_hosts = loadbalancer.gethosts()
hosts = nagios_hosts + lb_hosts
hosts.run_ssh_command_on_all_hosts('uname')
hosts.drain() # method of HostsLoadbalancer - drains just the loadbalancer-hosts
hosts.acknoledge_downtime() # method of NagiosHosts - does this just for the nagios hosts, is overlapping

这个问题的最佳解决方案是什么?

我想我可以以某种方式“复制所有方法”——就像这样: 对于 dir(other) 中的 x: setattr(self, x, getattr(other, x))

我在正确的轨道上吗?还是应该使用抽象基类?

【问题讨论】:

    标签: python multiple-inheritance


    【解决方案1】:

    一般来说这是个坏主意。您正在尝试将方法注入到类型中。话虽如此,您当然可以在 python 中执行此操作,但您必须意识到每次执行此操作时都希望创建一个新类型。这是一个例子:

    import copy
    
    class Base(dict):
        global_class_cache = {}
    
        def __init__(self, **data):
            self.local_data = data
    
        def __add__(self, other):
            new_instance = self._new_type((type(self), type(other)))()
            new_instance.update(copy.deepcopy(self).__dict__)
            new_instance.update(copy.deepcopy(other).__dict__)
            return new_instance
    
        def _new_type(self, parents):
            parents = tuple(parents)
            if parents not in Base.global_class_cache:
                name = '_'.join(cls.__name__ for cls in parents)
                Base.global_class_cache[parents] = type(name, parents, {})
            return Base.global_class_cache[parents]
    
    class A(Base):
        def a(self):
            print "test a"
    
    class B(Base):
        def b(self):
            print "test b"
    
    
    if __name__ == '__main__':
        a = A(a=1, b=2)
        b = B(c=1)
        c = a + b
        c.b() # should work
        c.a() # should work
        print c.__class__.__name__
    

    更新 我已经更新了示例以删除手动移动方法——我们在这里使用 mixins。

    【讨论】:

    • 很好,不知道 type('A_B', (A, B), {}) 的工作原理 - 看起来非常符合我的要求 - 在内部,我们仍在讨论我的一般方法是否正确 ;-)
    【解决方案2】:

    如果没有更多信息,很难回答您的问题。如果Base 应该是所有类的通用接口,那么您可以使用简单的继承来实现通用行为,同时保留子类的方法。例如,假设您需要一个基类,其中所有对象都有一个say_hola() 方法,但子类除了say_hola() 之外还可以有任意附加方法:

    class Base(object):
       def say_hola(self):
         print "hola"
    
    class C1(Base):
       def add(self, a, b):
          return a+b
    
    class C2(Base):
       def say_bonjour(self):
          return 'bon jour'
    

    这样C1C2 的所有实例除了它们的特定方法外,还有say_hola()

    更通用的模式是创建Mixin。来自维基百科:

    在面向对象编程中 语言,mixin 是一个类 提供一定的功能 由子类继承,而不是 用于实例化( 该类的对象的生成)。 从 mixin 继承不是一种形式 专业化,但更像是一个 收集功能的方法。一种 类可以继承其大部分或全部 来自一个或多个 mixin 的功能 通过多重继承。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-10
      • 1970-01-01
      • 1970-01-01
      • 2018-06-13
      • 2016-02-25
      相关资源
      最近更新 更多