Python继承-当搜索_mro__发现匹配项时以及当搜索未找到匹配项时记录日志

Python继承-当搜索_mro__发现匹配项时以及当搜索未找到匹配项时记录日志,python,python-2.7,inheritance,descriptor,method-resolution-order,Python,Python 2.7,Inheritance,Descriptor,Method Resolution Order,在Python中,假设我有一个如下所示的基本类结构: class Foo(object): def do_something(self): print 'doing a thing' def do_another_thing(self): print 'doing another thing' class Bar(Foo): def do_another_thing(self): super(bar, self).d

在Python中,假设我有一个如下所示的基本类结构:

class Foo(object):

    def do_something(self):
        print 'doing a thing'

    def do_another_thing(self):
        print 'doing another thing'

class Bar(Foo):

    def do_another_thing(self):
        super(bar, self).do_another_thing()
        print 'doing more stuff still'
我了解如何构造
\uuu mro\uuuu
属性,但我想添加日志记录,以便在输出中看到它在每个类调用时发现/调用了哪些方法。因此,举例来说,我希望它按照下面的注释进行记录:

f = Foo()
b = Bar()

f.do_something()
#print 'Implementing foo method do_something'

b.do_something()
#print 'Did not find method do_something for bar'
#print 'Implementing foo method do_something'

f.do_another_thing()
#print 'Implementing foo method do_another_thing'

b.do_another_thing()
#print 'Implementing bar method do_another_thing'
#print 'Implementing foo method do_another_thing'
我在
\uu getattribute\uu
\uu get\uuu
方面做了很多工作,但显然我对这些方法的理解还不够透彻,无法按预期实现。我还研究了如何使用装饰器,但我认为在某种程度上使用描述符可能是我们应该采取的方法

以下是我迄今为止所尝试的:

class Bar(Foo):

    def do_another_thing(self):
        super(Bar, self).do_another_thing()
        print 'doing more stuff still'

    def __getattribute__(self, key):
        self_dict = object.__getattribute__(type(self), '__dict__')
        if key in self_dict:
            print 'Implementing {} method {}'.format(type(self).__name__, key)
            v = object.__getattribute__(self, key)
            if hasattr(v, '__get__'):
                return v.__get__(None, self)
            return v
        print 'Did not find method {} for {}'.format(key, type(self).__name__)
        mro = object.__getattribute__(type(self), '__mro__')
        for thing in mro[1:]:
            v = thing.__getattribute__(self, key)
            if hasattr(v, '__get__'):
                return v.__get__(None, self)
            return v
我还在Foo中重新定义了这个
\uuuu getattribute\uuuu
,我的输出如下:

Implementing Foo method do_something
doing a thing
Did not find method do_something for Bar
Did not find method do_something for Bar
doing a thing
Implementing Foo method do_another_thing
doing another thing
Implementing Bar method do_another_thing
doing another thing
doing more stuff still

因此,我能够在继承的第一级捕获正确的日志记录,但无法正确地将调用从Bar传递到Foo,这样我就可以使用Foo的
\uuuuuuuu getattribute\uuuu

我做到了-这似乎在我的用例中起作用,尽管我可能在多重继承方面有问题:

class loggingObject(object):

    def __getattribute__(self, item):
        #we let the smart __getattribute__ method of object get the object we want
        v = object.__getattribute__(self, item)
        #if it's not a function, then we don't care about logging where it came from
        import types 
        if not isinstance(v, types.MethodType):
            #so we finish off default implementation
            if hasattr(v, '__get__'):
                return v.__get__(None, self)
            return v
        #get the dictionary of all explicitly defined items in the class that self is an instance of
        self_dict = object.__getattribute__(type(self), '__dict__')
        #if item is in self_dict, then the class that self is an instance of did implement this function 
        if item in self_dict:
            #we log, and then implement default __getattribute__ behaviour
            print 'Implementing {} method {}'.format(type(self).__name__, item) 
            if hasattr(v, '__get__'):
                return v.__get__(None, self)
            return v
        #if we are are, item is not explicitly in self_dict, and hence the class self is an instance of did not implement this function
        print 'Did not find explicit method {} for {}'.format(item, type(self).__name__)
        #unbind the function from self so it can be used for comparison
        actual_function = v.__func__
        #get the __mro__ for the class that self is an instance of
        mro = object.__getattribute__(type(self), '__mro__')
        #we loop through the mro to comapre functions in each class going up the inheritance tree until we find a match   
        for cls in mro[1:]:
            try:
                #get the function for cls
                function = object.__getattribute__(cls, '__dict__')[item]
                #if the function from class cls and the actual_function agree, that is where we got it from
                if function == actual_function:
                    print 'Implementing {} method {}'.format(cls.__name__, item)
                    break
            except KeyError:
                print 'Did not find explicit method {} for {}'.format(item, cls.__name__)
        #now that we have logged where we got the function from, default behaviour
        if hasattr(v, '__get__'):
            return v.__get__(None, self)
        return v

class Foo(loggingObject):

    def do_something(self):
        print 'doing a thing'

    def do_another_thing(self):
        print 'doing another thing'


class Bar(Foo):

    def do_another_thing(self):
        super(Bar, self).do_another_thing()
        print 'doing more stuff still'

你想用这个解决什么问题?如果您只是想调查正在发生的事情,使用调试器可能会更有效。我已经在
\uuuu getattribute\uuuu
中做了很多工作。如果你真的想这样做的话,那就是我提倡的方法;但你还没有向我们展示你在这里的尝试。那将是一个更好的起点。好的,这是一个公平的起点。让我来摆弄一下,我会用我所掌握的来更新这个问题。感谢您没有时间为您写出完整的解决方案,但我建议您查看
inspect
模块:@jornsharpe-我之所以要这样做纯粹是为了记录日志。其他在python/继承方面不是很强的人必须维护这段代码,因此注销树以及在日志文件中调用哪些方法将有助于他们在出现问题时识别和调试问题。