子インスタンスを操作しながら、親クラスのメソッド呼び出しの使用を追跡するために、非常に初歩的なアプローチを取りました。メソッドを変更して、__getattribute__
最初の親メソッド呼び出しを に書き込みchild.parent_method_dict
、その後child.parent_method_dict
、親クラスに戻すのではなく から呼び出すようにしました。私はここでそのような基本的な要素をいじっているので、親クラスのメソッドの使用状況を追跡するこの機能を構築するためのより安全またはより良い方法があるかどうかを尋ねなければなりません. 親クラスのメソッドを子クラスに割り当てて、使用する必要がないようにする必要がありますparent_method_dict
か?
class Parent(object):
def __init__(self):
pass
def a(self, *args, **kwargs):
return 'hello'
def b(self, *args, **kwargs):
return 'goodbye'
class Child(Parent):
def __init__(self):
super(Child, self).__init__()
self.count = 0
self.parent_method_dict = {}
def __getattribute__(self, attr):
if attr not in ['a', 'b']:
return super(Child, self).__getattribute__(attr)
_parent_dict = self.parent_method_dict
if attr in _parent_dict:
_attr = _parent_dict[attr]
_attr.func_count += 1
return _attr
_attr = super(Child, self).__getattribute__(attr)
print 'getting attribute {}'.format(attr)
if callable(_attr):
print 'can return value'
def _attr_val(*args, **kwargs):
print 'calculating value'
print 'self', self
self.count += 1
return_val = _attr(*args, **kwargs)
return return_val
_attr_val.func_count = 0
_parent_dict[attr] = _attr_val
return _attr_val
_parent_dict[attr] = _attr
return _attr
もっと複雑な形式の追跡、または追跡された情報の使用を実装できることを私は知っています。about モデルでは、何がどこに行くのかを知りたかっただけです。
>>> child = Child()
>>> child.count
0
>>> child.a()
getting attribute a
can return value
calculating value
self <Child object at 0x1036575d0>
'hello'
>>> child.a()
calculating value
self <Child object at 0x1036575d0>
'hello'
>>> child.b()
getting attribute b
can return value
calculating value
self <Child object at 0x1036575d0>
'goodbye'
>>> child.count
3
>>> child.a.func_count
2
>>> child.b.func_count
1
>>> child.parent_method_dict
{'a': <function _attr_val at 0x1035d5f50>, 'b': <function _attr_val at 0x1035d5848>}
メソッドは期待値を返します。異なるカウントは正確です。
@Marcinに対処するための追加のメモ:
ここに新しいParent
クラスがあります:
class Parent(object):
def __init__(self):
pass
def a(self, *args, **kwargs):
print 'hello'
return self
def b(self, *args, **kwargs):
print 'goodbye'
return self
中Child.__init__
に、 を追加しましself.sequence = []
た。中def _attr_val(*args, **kwargs)
に、 を追加しましself.sequence.append(attr)
た。だから今私は得る:
>>> c = Child()
>>> c.a().b().a().a().b()
getting attribute a
can return value
calculating value
self <Child object at 0x10361fe90>
hello
getting attribute b
can return value
calculating value
self <Child object at 0x10361fe90>
goodbye
calculating value
self <Child object at 0x10361fe90>
hello
calculating value
self <Child object at 0x10361fe90>
hello
calculating value
self <Child object at 0x10361fe90>
goodbye
<Child object at 0x10361fe90>
>>> c.sequence
['a', 'b', 'a', 'a', 'b']
これで、チェーンされたメソッドのシーケンスを追跡できます。したがってc.a().b()....n()
、非常に高価で、実際のシーケンスに大きく依存していたとしましょう。これで、計算に必要なシーケンスによって識別される値を保存できます。さらに、後でシーケンスを簡単に複製できます。