在使用子实例时,我采用了一种非常基本的方法来跟踪父类方法调用的使用。我修改了__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
我知道我可以实施更复杂的跟踪形式,或使用跟踪信息。关于模型,我只想看看会发生什么。
>>> 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()
是非常昂贵的,也非常依赖于实际的序列。我现在可以保存由计算它所需的序列标识的值。另外,我可以在以后轻松复制序列。