当前位置:  开发笔记 > 编程语言 > 正文

Python:使用pre和post方法包装方法调用

如何解决《Python:使用pre和post方法包装方法调用》经验,为你挑选了1个好方法。

我正在将类A(我从其他人导入,因此我无法修改它)实例化到我的类X.

有没有办法可以拦截或包装对A中方法的调用?即,在下面的代码中我可以打电话

x.a.p1()

并获得输出

X.pre
A.p1
X.post

很多TIA!

class A:
    # in my real application, this is an imported class
    # that I cannot modify
    def p1(self): print 'A.p1'

class X:
    def __init__(self):
        self.a=A()
    def pre(self): print 'X.pre'
    def post(self): print 'X.post'

x=X()
x.a.p1()

Thomas Watne.. 6

以下是我和我的同事提出的解决方案:

from types import MethodType

class PrePostCaller:
    def __init__(self, other):
        self.other = other

    def pre(self): print 'pre'
    def post(self): print 'post'

    def __getattr__(self, name):
        if hasattr(self.other, name):
            func = getattr(self.other, name)
            return lambda *args, **kwargs: self._wrap(func, args, kwargs)
        raise AttributeError(name)

    def _wrap(self, func, args, kwargs):
        self.pre()
        if type(func) == MethodType:
            result = func( *args, **kwargs)
        else:
            result = func(self.other, *args, **kwargs)
        self.post()
        return result

#Examples of use
class Foo:
    def stuff(self):
        print 'stuff'

a = PrePostCaller(Foo())
a.stuff()

a = PrePostCaller([1,2,3])
print a.count()

得到:

pre
stuff
post
pre
post
0

因此,在创建对象的实例时,请使用PrePostCaller对象进行包装.之后,继续使用该对象,就好像它是包装对象的实例一样.使用此解决方案,您可以基于每个实例进行包装.



1> Thomas Watne..:

以下是我和我的同事提出的解决方案:

from types import MethodType

class PrePostCaller:
    def __init__(self, other):
        self.other = other

    def pre(self): print 'pre'
    def post(self): print 'post'

    def __getattr__(self, name):
        if hasattr(self.other, name):
            func = getattr(self.other, name)
            return lambda *args, **kwargs: self._wrap(func, args, kwargs)
        raise AttributeError(name)

    def _wrap(self, func, args, kwargs):
        self.pre()
        if type(func) == MethodType:
            result = func( *args, **kwargs)
        else:
            result = func(self.other, *args, **kwargs)
        self.post()
        return result

#Examples of use
class Foo:
    def stuff(self):
        print 'stuff'

a = PrePostCaller(Foo())
a.stuff()

a = PrePostCaller([1,2,3])
print a.count()

得到:

pre
stuff
post
pre
post
0

因此,在创建对象的实例时,请使用PrePostCaller对象进行包装.之后,继续使用该对象,就好像它是包装对象的实例一样.使用此解决方案,您可以基于每个实例进行包装.

推荐阅读
帆侮听我悄悄说星星
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有