記述子/デコレータを入れ子にしようとすると何が起こるのか分かりにくいです。私はPython 2.7を使用しています。Pythonで記述子/デコレータを入れ子にする
たとえば、のはproperty
とclassmethod
次の単純化されたバージョンを見てみましょう:
class MyProperty(object):
def __init__(self, fget):
self.fget = fget
def __get__(self, obj, objtype=None):
print 'IN MyProperty.__get__'
return self.fget(obj)
class MyClassMethod(object):
def __init__(self, f):
self.f = f
def __get__(self, obj, objtype=None):
print 'IN MyClassMethod.__get__'
def f(*args, **kwargs):
return self.f(objtype, *args, **kwargs)
return f
が巣にそれらをしよう:
class A(object):
# doesn't work:
@MyProperty
@MyClassMethod
def klsproperty(cls):
return 555
# works:
@MyProperty
def prop(self):
return 111
# works:
@MyClassMethod
def klsmethod(cls, x):
return x**2
% print A.klsproperty
IN MyProperty.__get__
...
TypeError: 'MyClassMethod' object is not callable
インナー記述MyClassMethod
の__get__
メソッドが呼び出さ取得されていません。 理由を把握するために失敗すると、私は(私はと思われるもの)ノーオペレーション記述子を中に投げてみました:
class NoopDescriptor(object):
def __init__(self, f):
self.f = f
def __get__(self, obj, objtype=None):
print 'IN NoopDescriptor.__get__'
return self.f.__get__(obj, objtype=objtype)
:
class B(object):
# works:
@NoopDescriptor
@MyProperty
def prop1(self):
return 888
# doesn't work:
@MyProperty
@NoopDescriptor
def prop2(self):
return 999
% print B().prop1
IN NoopDescriptor.__get__
IN MyProperty.__get__
888
% print B().prop2
IN MyProperty.__get__
...
TypeError: 'NoopDescriptor' object is not callable
なぜB().prop1
が動作し、B().prop2
は理解できません。
質問:私が間違っているのは何
- ?
object is not callable
エラーが発生するのはなぜですか? - 正しい方法はありますか?例えばデコレータは、デコレータは、それがそのように飾る機能が呼び出され、パラメータを指定せずに使用した場合
MyClassMethod
及びMyProperty
(又はclassmethod
とproperty
)この場合
これを直感的に理解するための鍵は、 '@ MyProperty'がメソッドではなく_data_属性のように動作するものを作成するため、メソッドディスクリプタでネストすることができないということです。その直感的な理解だけがあなたを今までに導きます。完全な話はisedevの答えです。 – abarnert