Python で問題が発生しましたが、明確な解決策が見つかりません...
いくつかのメソッドを呼び出すときに、メソッドの実行前と実行後にいくつかのコードを実行したい。context
(他の多くのことの中で)変数を自動的に設定および消去するため。
これを実現するために、次のメタクラスを宣言しました。
class MyType(type):
def __new__(cls, name, bases, attrs):
#wraps the 'test' method to automate context management and other stuff
attrs['test'] = cls.other_wrapper(attrs['test'])
attrs['test'] = cls.context_wrapper(attrs['test'])
return super(MyType, cls).__new__(cls, name, bases, attrs)
@classmethod
def context_wrapper(cls, operation):
def _manage_context(self, *args, **kwargs):
#Sets the context to 'blabla' before the execution
self.context = 'blabla'
returned = operation(self, *args, **kwargs)
#Cleans the context after execution
self.context = None
return returned
return _manage_context
@classmethod
def other_wrapper(cls, operation):
def _wrapped(self, *args, **kwargs):
#DO something with self and *args and **kwargs
return operation(self, *args, **kwargs)
return _wrapped
これは魅力のように機能します:
class Parent(object):
__metaclass__ = MyType
def test(self):
#Here the context is set:
print self.context #prints blabla
しかし、 をサブクラス化するとすぐにParent
、親メソッドを次のように呼び出すと、問題が発生しますsuper
。
class Child(Parent):
def test(self):
#Here the context is set too
print self.context #prints blabla
super(Child, self).test()
#But now the context is unset, because Parent.test is also wrapped by _manage_context
#so this prints 'None', which is not what was expected
print self.context
新しい値に設定する前にコンテキストを保存することを考えましたが、それは問題を部分的にしか解決しません...
確かに、(ちょっと待ってください、これは説明が難しいです)、親メソッドが呼び出され、ラッパーが実行されますが、それらは を受け取り*args
、**kwargs
アドレス指定されますParent.test
whileself
はChild
インスタンスであるためself
、*args
and **kwargs
(たとえば、自動検証の目的で)、例:
@classmethod
def validation_wrapper(cls, operation):
def _wrapped(self, *args, **kwargs):
#Validate the value of a kwarg
#But if this is executed because we called super(Child, self).test(...
#`self.some_minimum` will be `Child.some_minimum`, which is irrelevant
#considering that we called `Parent.test`
if not kwarg['some_arg'] > self.some_minimum:
raise ValueError('Validation failed')
return operation(self, *args, **kwargs)
return _wrapped
したがって、基本的に、この問題を解決するには、次の 2 つの解決策があります。
メソッドが呼び出されたときにラッパーが実行されるのを防ぎます
super(Child, self)
self
常に「正しい」タイプのを持っている
両方の解決策は私には不可能に思えます...誰かがこれを解決する方法について考えを持っていますか? 提案 ?