Что изящные пути состоят в том, чтобы сделать MixIns в Python?

Я должен найти изящный способ сделать 2 вида MixIns.

Во-первых:

class A(object):
    def method1(self):
        do_something()

Теперь, a 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 - это в порядке, просто ища самые простые способы достигнуть этого.

Это довольно тривиальные проблемы, и я на самом деле решил их, но мое решение испорчено.

Fisrt один при помощи self._old_method1 = self.method1(); self.method1() = self._new_method1(); и запись _new_method1() это звонит в _old_method1().

Проблема: несколько MixIns все переименуют к _old_method1, и это неэлегантно.

Второй MixIn каждый был решен путем создания фиктивного метода call_mixin(self): pass и введение его между вызовами и определением self.call_mixin(). Снова неэлегантный и повредится на нескольких MixIns..

Какие-либо идеи?


Благодаря Boldewyn я нашел изящное решение сначала один (я имею, забыл, что можно создать декораторов на лету, не изменяя исходный код):

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

Все еще ища идеи для второй (эта идея не будет соответствовать, так как я должен ввести в старом методе, не снаружи, как в этом случае).


Решение для второго ниже, заменяя "pass_func" с lambda:0.

7
задан Slava V 3 May 2010 в 15:49
поделиться

2 ответа

Вот еще один способ реализовать MixInClass1, MixinClass2:

Декораторы полезны, когда вам нужно обернуть множество функций. Поскольку MixinClass1 должен содержать только одну функцию, я думаю, что для monkey-patch это более понятно:

Использование двойного подчеркивания для __ 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()
3
ответ дан 7 December 2019 в 05:19
поделиться

Я думаю, это можно сделать вполне по-питоновски, используя декораторы. (PEP 318, тоже)

5
ответ дан 7 December 2019 в 05:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: