Python类是否可以不从多个类继承,而是具有“选择"属性?继承? [英] Can a Python class not inherit from multiple classes, but have a "choice" of inheritance?

查看:164
本文介绍了Python类是否可以不从多个类继承,而是具有“选择"属性?继承?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在使用3Rd派对应用程序.该第三方应用定义了以下类别:

 class VeryBaseClass(object):
      def __init__():
          pass

 class BaseClass(VeryBaseClass):
     def specific_method():
          pass

然后,抢劫这些话题:

 class Componenent[1,2,3,4....129883](BaseClass):
     def other_specific_method():
         pass

我无法修改任何这些类.因此,对于我来说,这里要覆盖/补充方法,我只需要创建一个从Component继承的类,即可在其中轻松地更改方法.

问题是,使MyComponent1,然后MyComponent2,MyComponent3等...全部用于在类的内容中复制粘贴完全相同的代码,并且仅更改继承是非常烦人的,而且根本不干! /p>

因此,有没有一种方法可以创建此类,例如:

class MyComponentGeneric(Component1, Component2, Component3....):
      pass

根据我对实例的声明,MyComponentGeneric不会从列出的每个类中继承,但可以从一个或另一个类继承吗?

谢谢!

使用更具体的代码进行编辑:

实际上,我已经尝试过所有答案中涉及的内容,但我总是最终会遇到相同的错误:

我按照Chepney的建议建造了一家工厂:

# This method is the one I use as a replacement
def newrender(self, name, value, attrs=None):
    result = super().render(name, value, attrs)
    if self.image is None:
        return result
    else:
        return '<img class="form-image" height="100" width="100" src="{}"/>'.format(self.image.url) + result


def MyWidgetFactory(widget, picture):
     newclass = type("WithImage" + widget.__name__, (widget,), dict(render=newrender))
     newclass.image = image
     return newclass()

但是,一旦我的newrender方法启动,我就会收到此错误:

result = super().render(name, value, attrs) RuntimeError: super(): __class__ cell not found

是因为工厂使用不当还是其他原因造成的?

5分钟后编辑 好的,我只需要通过用super(type(self),self)调用它来填充超级单元.不太确定它是如何工作的,但是,它起作用了!

谢谢大家!

解决方案

这是字典的用例(如果字典键只是连续整数的序列,则可能是列表):

base_classes = {
    1: Component1,
    2: Component2,
    # ...
}

def ComponentFactory(comp_type):
    return base_classes(comp_type)()

在这里,ComponentFactory为您创建实例,而不是创建一个新类,该类本质上只会包装一个现有类而不实际添加它.


如果您真的需要一种新类型,也可以在工厂中创建它:

def ComponentFactory(comp_type):
    new_type = type('SomeTypeName', (base_classes[comp_type],), {})
    return new_type()

但是,您可能应该注意,每个真实类只能创建一个一个这样的包装器,以免最终不会得到一堆相同的单例类.

I'm currently working with a 3Rd party app. This 3rd party app has thoses class defined :

 class VeryBaseClass(object):
      def __init__():
          pass

 class BaseClass(VeryBaseClass):
     def specific_method():
          pass

And then, looots of theses:

 class Componenent[1,2,3,4....129883](BaseClass):
     def other_specific_method():
         pass

I can't modify any of these classes . So , for me to override/supplement methods here, I just have to create a class that inherits from Component, where I can change the methods effortlessly.

The problem is, making MyComponent1, then MyComponent2, MyComponent3, etc... all for copy-pasting the exact same code in the content of the class and just changing the inheritance is very annoying, and not DRY at all!

So, is there a way to create, for example , this class:

class MyComponentGeneric(Component1, Component2, Component3....):
      pass

Where MyComponentGeneric would not inherit from EVERY class listed, but could inherit from one OR another, depending of my declaration of the instance ?

Thanks!

Edit with more concrete code :

Actually, I've tried things that belonged in every answer, but I always end up facing the same error :

I made a Factory as Chepney advised :

# This method is the one I use as a replacement
def newrender(self, name, value, attrs=None):
    result = super().render(name, value, attrs)
    if self.image is None:
        return result
    else:
        return '<img class="form-image" height="100" width="100" src="{}"/>'.format(self.image.url) + result


def MyWidgetFactory(widget, picture):
     newclass = type("WithImage" + widget.__name__, (widget,), dict(render=newrender))
     newclass.image = image
     return newclass()

But as soon as my newrender method launches, I get this error :

result = super().render(name, value, attrs) RuntimeError: super(): __class__ cell not found

Is it because of a bad usage of the factory or something else ?

5 minutes later edit Okay, I just had to populate the super cell by calling it with super(type(self), self). Not quite sure how it works but, heh, it worked!

Thanks everyone !

解决方案

This is a use case for a dictionary (or possibly a list, if the dictionary keys are just a sequence of consecutive integers):

base_classes = {
    1: Component1,
    2: Component2,
    # ...
}

def ComponentFactory(comp_type):
    return base_classes(comp_type)()

Here, ComponentFactory creates the instance for you, rather than creating a new class that essentially would just wrap an existing class without actually adding to it.


If you really need a new type, you can create that in the factory as well:

def ComponentFactory(comp_type):
    new_type = type('SomeTypeName', (base_classes[comp_type],), {})
    return new_type()

However, you should probably take care that you only create one such wrapper per real class, so that you don't end up with a bunch of identical singleton classes.

这篇关于Python类是否可以不从多个类继承,而是具有“选择"属性?继承?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆