修改Python可调用对象,使其在调用前后执行before()和after()
我不太确定这样做是否是让 before
和 after
函数在 f1()
函数前后被调用的最佳方法。
class ba(object):
def __init__(self, call, before, after):
self.call = call
self.before = before
self.after = after
def __call__(self, *args):
self.before()
r = self.call(*args)
self.after()
return r
class test1(object):
def mybefore(self):
print "before func call"
def myafter(self):
print "after func call"
def meth1(a1, a2):
print "meth1(a1=%d, a2=%d)" % (a1, a2)
t = test1()
wmeth1 = ba(meth1, t.mybefore, t.myafter)
wmeth1(1, 2)
请给点建议。
2 个回答
3
你可以使用@contextmanager
这个装饰器,它在contextlib
模块里。然后配合with
语句来实现类似下面的功能:
from contextlib import contextmanager
class test1(object):
def mybefore(self):
print "before func call"
def myafter(self):
print "after func call"
@contextmanager
def wrapper(cls):
test = cls()
test.mybefore()
try:
yield
finally:
test.myafter()
def f1(a1, a2):
print "f1(a1=%d, a2=%d)" % (a1, a2)
with wrapper(test1):
f1(1, 2)
14
我会使用一个装饰器,像这样:
from functools import wraps
class withBeforeAfter(object):
def __init__(self, before, after):
self.before = before
self.after = after
def __call__(self, wrappedCall):
@wraps(wrappedCall)
def wrapCall(*args, **kwargs):
try:
self.before()
r = wrappedCall(*args, **kwargs)
finally:
self.after()
return r
return wrapCall
# to use it:
@withBeforeAfter(myBefore, myAFter)
def myFunc(...):
...
# or:
def myFunc(...):
...
# later...
myFunc = withBeforeAfter(myBefore, myAfter)(myFunc)