我目前正在使用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等...所有用于复制粘贴类的内容中完全相同的代码,只是更改继承是非常烦人的,而不是DRY! / p>
那么,有没有办法创建这个类:
class MyComponentGeneric(Component1, Component2, Component3....):
pass
MyComponentGeneric不会从列出的每个类继承,但可以从一个OR继承,具体取决于我的实例声明?
谢谢!
使用更具体的代码进行编辑:
实际上,我已经尝试了每个答案中都有的东西,但我总是面临同样的错误:
我做了一个工厂,因为切普尼建议:
# 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)调用超级单元格来填充它。不太确定它是如何工作的,但是,嘿,它有效!
谢谢大家!
答案 0 :(得分:3)
这是字典的用例(如果字典键只是连续整数的序列,则可能是列表):
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()
但是,您应该注意每个真实类只创建一个这样的包装器,这样您就不会得到一堆相同的单例类。
答案 1 :(得分:1)
如果不仔细查看代码库,很难回答。 但是,对我而言,看起来你可以用猴子修补来解决这个问题。
换句话说,您可以向Component1,Component2,Component3添加方法,甚至可以替换这些类的现有方法。
Remeamber python肯定是OOP,但它也提供了一套&#34;动态&#34;工具(例如猴子路径)你可以在很多场景中使用得很有效。
干杯
Chralie
答案 2 :(得分:1)
一,你不会命名你的类MyComponent2112,你有一个字典作为值。更容易使用。
然后只需在循环中创建类:
import third_party_module
mycomponents = dict()
for componentname in dir(third_party_module):
if not componentname.startswith('Component'): continue
baseclass = getattr(third_party_module, componentname)
if not issubclass(baseclass, third_party_module.VeryBaseClass): continue
number = int(componentname[9:])
class MyComponent(baseclass):
# Your updates here
mycomponents[number] = MyComponent