基本的に、私が欲しいのはこれを行うことです:
class B:
def fn(self):
print 'B'
class A:
def fn(self):
print 'A'
@extendInherit
class C(A,B):
pass
c=C()
c.fn()
そして、出力を
A
B
extendInheritデコレータをどのように実装しますか?
基本的に、私が欲しいのはこれを行うことです:
class B:
def fn(self):
print 'B'
class A:
def fn(self):
print 'A'
@extendInherit
class C(A,B):
pass
c=C()
c.fn()
そして、出力を
A
B
extendInheritデコレータをどのように実装しますか?
これはデコレータの仕事ではありません。クラスの通常の動作を完全に変更したいので、これは実際にはメタクラスの仕事です。
import types
class CallAll(type):
""" MetaClass that adds methods to call all superclass implementations """
def __new__(meta, clsname, bases, attrs):
## collect a list of functions defined on superclasses
funcs = {}
for base in bases:
for name, val in vars(base).iteritems():
if type(val) is types.FunctionType:
if name in funcs:
funcs[name].append( val )
else:
funcs[name] = [val]
## now we have all methods, so decorate each of them
for name in funcs:
def caller(self, *args,**kwargs):
""" calls all baseclass implementations """
for func in funcs[name]:
func(self, *args,**kwargs)
attrs[name] = caller
return type.__new__(meta, clsname, bases, attrs)
class B:
def fn(self):
print 'B'
class A:
def fn(self):
print 'A'
class C(A,B, object):
__metaclass__=CallAll
c=C()
c.fn()
個人的には、新しいスタイルのクラスとを使用するため、デコレータでこれを実行しようとはしませんsuper()
。次のことが達成できます。
>>> class A(object):
... def __init__(self):
... super(A, self).__init__()
... print "A"
...
>>> class B(object):
... def __init__(self):
... super(B, self).__init__()
... print "B"
...
>>> class C(A, B):
... def __init__(self):
... super(C, self).__init__()
...
>>> foo = C()
B
A
メソッド呼び出しも同じように機能すると思います。
メタクラスは可能な解決策ですが、やや複雑です。 super
非常に簡単に実行できます (もちろん、新しいスタイル クラスを使用します。新しいコードでレガシー クラスを使用する理由はありません!):
class B(object):
def fn(self):
print 'B'
try: super(B, self).fn()
except AttributeError: pass
class A(object):
def fn(self):
print 'A'
try: super(A, self).fn()
except AttributeError: pass
class C(A, B): pass
c = C()
c.fn()
単一または複数の継承の任意の順序をサポートするには、try/except が必要です (ある時点で、メソッド解決順序 MRO に沿って、 という名前のメソッドを定義するベースがなくなるためfn
、結果の をキャッチして無視する必要がありますAttributeError
) 。 . しかし、ご覧のとおり、コメントに基づいて別の回答に基づいて考えているように見えるものとは異なり、fn
そのようなオーバーライドでそのクラスに固有の何かをする必要がない限り、必ずしも最下位クラスでオーバーライドする必要はありません-super
動作します純粋に継承された (オーバーライドされていない) メソッドでも問題ありません。