3

私は、サブクラスがオプションで指定された名前のメソッドを定義することができるクラス階層を持っていdo_itますdo_all. これを達成するために私が得ることができる最も近いものは次のようなものです:

class A(object):
    def do_it(self):
        print 'Do A'

    def do_all(self):
        # Better, from comments and answers: vars(type(self))
        for c in reversed(self.__class__.__mro__[:-1]):
            c.do_it(self)

class B(A):
    def do_it(self):
        print 'Do B'

class C(B):
    def no_do_it(self):
        pass

class D(C):
    def do_it(self):
        print 'Do D'

B().do_all()これはほぼ意図したとおりに機能します。たとえば、

Do A
Do B

しかし、その結果、その子孫のすべてのクラスに対してBsが重複して呼び出されます。do_itたとえばD().do_all()

Do A
Do B
Do B
Do D

do_it親を実装していないクラスからの親への重複呼び出しを回避するにはどうすればよいですか? これは、私がやろうとしていることを達成する正しい方法ですか?

4

1 に答える 1

4

関数が既に表示されているかどうかを確認できます。

def do_all(self):
    seen = set()
    for c in reversed(self.__class__.__mro__[:-1]):
        if c.do_it not in seen:
            seen.add(c.do_it)
            c.do_it(self)

c.do_it.__func__Python 2 では、バインドされていないメソッドから関数を as (または use )で抽出する必要があることに注意してくださいsix.get_unbound_function

別の方法は、次を調べること__dict__です。

def do_all(self):
    for c in reversed(self.__class__.__mro__[:-1]):
        if 'do_it' in c.__dict__:
            c.do_it(self)
于 2014-01-07T18:43:30.297 に答える