python继承 - 搜索__mro__搜索匹配时,登录时



在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'

我了解如何构建__mro__属性,但是我想添加日志记录,以便在输出中看到每个类拨打其呼叫时发现/调用的方法。因此,例如,我希望它按照下面的注释来登录:

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'

我已经摆弄__getattribute____get__,但显然我不太了解这些方法无法根据需要实现。我还考虑使用装饰器,但我认为以某种方式使用描述符可能是在这里走的路线。

这是我到目前为止尝试过的:

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中重新定义了此__getattribute__,我的输出如下:

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的__getattribute__

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

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'

相关内容

  • 没有找到相关文章

最新更新