0

在处理子实例时,我采用了一种非常基本的方法来跟踪父类方法调用的使用。我已经修改了该__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()是一个非常昂贵的,也非常依赖于实际的序列。我现在可以保存由计算它所需的序列标识的值。此外,我可以在以后轻松复制该序列。

4

0 回答 0