我需要找到一种优雅的方式来做两种MixIns。
首先
class A(object):
def method1(self):
do_something()
现在,MixInClass
应该method1
执行此操作:do_other()
- > A.method1()
- > do_smth_else()
- 即基本上“包裹”旧功能。我很确定必须有一个很好的解决方案。
第二
class B(object):
def method1(self):
do_something()
do_more()
在这种情况下,我希望MixInClass2
能够在do_something()
和do_more()
之间注入自己,即:do_something()
- > MixIn.method1
- > do_more()
。我理解这可能需要修改class B
- 这没关系,只是寻找最简单的方法来实现这一点。
这些都是非常微不足道的问题,我实际上解决了它们,但我的解决方案被污染了。
使用self._old_method1 = self.method1(); self.method1() = self._new_method1();
并撰写调用_new_method1()
的{{1}}即可。
问题:多个MixIns都会重命名为_old_method1而且它不够优雅。
第二个MixIn通过创建一个虚方法_old_method1()
并在调用之间注入并定义call_mixin(self): pass
来解决。再次不优雅,将打破多个MixIns ..
有什么想法吗?
感谢Boldewyn,我找到了第一个优雅的解决方案(我忘了你可以在不修改原始代码的情况下即时创建装饰器):
self.call_mixin()
仍然在寻找第二个想法(这个想法不适合,因为我需要注入旧方法,而不是在外面,就像在这种情况下)。
第二个解决方案如下,将“pass_func”替换为class MixIn_for_1(object):
def __init__(self):
self.method1 = self.wrap1(self.method1)
super(MixIn_for_1, self).__init__()
def wrap1(self, old):
def method1():
print "do_other()"
old()
print "do_smth_else()"
return method1
。
答案 0 :(得分:5)
我认为,可以使用decorators以相当Pythonic的方式处理。 (PEP 318也是)
答案 1 :(得分:3)
这是实现MixInClass1,MixinClass2的另一种方法:
当您需要包装许多函数时,装饰器很有用。由于MixinClass1
只需要包装一个函数,我认为猴子补丁更清楚:
在__old_method1
和__method1
中使用双下划线可在MixInClass1
中发挥有用的作用。由于Python的名称修改约定,使用双下划线将这些属性本地化为MixinClass1
,并允许您为其他混合类使用完全相同的属性名称,而不会导致不必要的名称冲突。
class MixInClass1(object):
def __init__(self):
self.__old_method1,self.method1=self.method1,self.__method1
super(MixInClass1, self).__init__()
def __method1(self):
print "pre1()"
self.__old_method1()
print "post1()"
class MixInClass2(object):
def __init__(self):
super(MixInClass2, self).__init__()
def method1_hook(self):
print('MixIn method1')
class Foo(MixInClass2,MixInClass1):
def method1(self):
print "do_something()"
getattr(self,'method1_hook',lambda *args,**kw: None)()
print "do_more()"
foo=Foo()
foo.method1()