python:基类中的多重继承和__add __()

时间:2010-09-16 15:24:13

标签: python multiple-inheritance

我有一个我希望处理__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的子类) - 这个优惠一些基本方法,例如run_ssh_commmand_on_all_hosts()

现在我有一个子类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

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

我想我可以以某种方式“复制所有方法” - 像这样:     for d in dir(other):         setattr(self,x,getattr(other,x))

我是否在正确的轨道上?或者我应该使用抽象基类?

2 个答案:

答案 0 :(得分: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。

答案 1 :(得分:0)

如果没有更多信息,很难回答你的问题。如果Base应该是所有类的公共接口,那么您可以使用简单继承来实现常见行为,同时保留子类的方法。例如,假设您需要一个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继承并不是一种形式   专业化但相当于一个   收集功能的方法。一个   class可以继承其大部分或全部   来自一个或多个mixins的功能   通过多重继承。