Python mixin有一个无法覆盖的方法(默认情况下)?

时间:2015-09-25 14:13:52

标签: python python-2.7

在Python中,我使用的框架可以让我进入这样的生命周期:

class MyView(BaseView):
    def pre_save(self):
        print "view presave"

我想编写一个mixin来在pre_save中执行某些操作,但是我已经在使用pre_save的许多类中拥有大量代码,而不调用super()。如果我像这样添加我的mixin:

class MyMixin(object):
    def pre_save(self):
        print "mixin presave"

class MyView(MyMixin, BaseView):
    def pre_save(self):
        print "view presave"

它自然会覆盖mixin,并打印"查看presave"只要。是否还有另一种狡猾的方式我可以写MyMixin以强制所有客户端视图都不记得拨打super()

1 个答案:

答案 0 :(得分:1)

这个答案是概念证明,而不是推荐。 请勿在生产代码中执行此操作。您将创建维护噩梦。我同意那些评论你的问题,即唯一安全的方法是编辑派生类。

尽管如此,技术上可以使用metaclass

def do_evil(self, method):
    print "doing evil"
    MyMixin.pre_save(self)
    method(self)

class ConcentratedEvil(type):
    tainted_classes = ['MyView'] # Add others as needed
    def __new__(mcs, name, bases, dict):
        if name in mcs.tainted_classes:
            print "tainting {0} with the power of evil".format(name)
            old_method = dict['pre_save']
            dict['pre_save'] = lambda x: do_evil(x, old_method)
            print dict.keys()
        return type.__new__(mcs, name, bases, dict)

class BaseView(object):
    pass

class MyMixin(object):
    __metaclass__ = ConcentratedEvil
    def pre_save(self):
        print "mixin presave"

class MyView(MyMixin, BaseView):
    def pre_save(self):
        print "view presave"

您可以这样做:

>>> view = MyView()
>>> view.pre_save()
doing evil
mixin presave
view presave
>>>

我认为这只有在MyMixin位于基类列表的前面时才有效。