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

发布于 2024-09-19 11:04:47 字数 1484 浏览 2 评论 0原文

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

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

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

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

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

I've got a base class where I want to handle __add__() and want to support when __add__ing two subclass instances - that is have the methods of both subclasses in the resulting instance.

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

Edit: To be more specific: I've got a class Hosts that holds a dict(host01=.., host02=..) (hence the subclassing of dict) - this offers some base methods such as run_ssh_commmand_on_all_hosts()

Now I've got a subclass HostsLoadbalancer that holds some special methods such as drain(), and I've got a class HostsNagios that holds some nagios-specific methods.

What I'm doing then, is something like:

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

What is the best solution for this problem?

I think I can somehow "copy all methods" - like this:
for x in dir(other):
setattr(self, x, getattr(other, x))

Am I on the right track? Or should I use Abstract Base Classes?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

漫雪独思 2024-09-26 11:04:47

一般来说,这是一个坏主意。您正在尝试将方法注入到类型中。话虽如此,您当然可以在 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__

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

In general this is a bad idea. You're trying to inject methods into a type. That being said, you can certainly do this in python, but you'll have to realize that you want to create a new type each time you do this. Here's an example:

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
I've updated the example to remove manually moving the methods -- we're using mixins here.

宁愿没拥抱 2024-09-26 11:04:47

如果没有更多信息,很难回答你的问题。如果 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 继承不是一种形式
的专业化,而是
收集功能的手段。一个
类可以继承其大部分或全部
来自一个或多个 mixins 的功能
通过多重继承。

It is difficult to answer your question without more information. If Base is supposed to be a common interface to all classes, then you could use simple inheritance to implement the common behavior while preserving the methods of the subclasses. For instance, imagine that you need a Base class where all the objects have a say_hola() method, but subclasses can have arbitrary additional methods in addition to 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'

This way all instances of C1 and C2 have say_hola() in addition to their specific methods.

A more general pattern is to create a Mixin. From Wikipedia:

In object-oriented programming
languages, a mixin is a class that
provides a certain functionality to be
inherited by a subclass, while not
meant for instantiation (the
generation of objects of that class).
Inheriting from a mixin is not a form
of specialization but is rather a
means of collecting functionality. A
class may inherit most or all of its
functionality from one or more mixins
through multiple inheritance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文