2010-09-16 1 views
3

У меня есть базовый класс, где я хочу обрабатывать __add__() и хочу поддерживать, когда __add__ с двумя экземплярами подкласса - это методы обоих подклассов в результирующем экземпляре ,python: множественное наследование и __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 

Что является лучшим решением для этой задачи?

Я думаю, что можно как-то «копировать все методы» - как это: для й в реже (другой): SetAttr (я, х, GetAttr (другой, х))

Я на правах отслеживать? Или я должен использовать абстрактные базовые классы?

ответ

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__ 

UPDATE Я обновил пример, чтобы удалить вручную двигая методы - мы используем Примеси здесь.

+0

хороший, не знал о 'type ('A_B', (A, B), {})' works - это очень много выглядит, что я искал - внутренне мы все еще обсуждаем, верно, хотя ;-) – hansaplast

0

Трудно ответить на ваш вопрос без дополнительной информации. Если 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' 

Таким образом, все экземпляры C1 и C2 имеют say_hola() в дополнении к их конкретным методам.

Более общий шаблон - создать Mixin. Материал из Википедии:

В объектно-ориентированном программировании языков, а также примесь является классом, который обеспечивает определенную функциональность, чтобы быть наследуется подклассом, а не предназначена для создания экземпляра (в генераций объектов, которые класс). Наследование из mixin - это не форма специализации, а скорее средства сбора функциональности.Класс может наследовать большинство или все его функции из одного или нескольких миксинов через множественное наследование.