如果您想在所有crawl_* 方法之后隐式运行一个方法,最简单的解决方案可能是设置一个元类,它将以编程方式为您包装这些方法。从这个开始,一个简单的包装函数:
import functools
def wrapit(func):
@functools.wraps(func)
def _(self, *args, **kwargs):
func(self, *args, **kwargs)
self.save_to_db()
return _
这是一个包装func的基本装饰器,调用
self.save_to_db() 在调用func 之后。现在,我们建立一个元类
这将以编程方式将其应用于特定方法:
class Wrapper (type):
def __new__(mcls, name, bases, nmspc):
for attrname, attrval in nmspc.items():
if callable(attrval) and attrname.startswith('crawl_'):
nmspc[attrname] = wrapit(attrval)
return super(Wrapper, mcls).__new__(mcls, name, bases, nmspc)
这将遍历包装类中的方法,寻找
以crawl_ 开头的方法名并用我们的
装饰器函数。
最后是被包装的类本身,它将Wrapper 声明为
元类:
class Wrapped (object):
__metaclass__ = Wrapper
def crawl_1(self):
print 'this is crawl 1'
def crawl_2(self):
print 'this is crawl 2'
def this_is_not_wrapped(self):
print 'this is not wrapped'
def save_to_db(self):
print 'saving to database'
鉴于上述情况,我们得到以下行为:
>>> W = Wrapped()
>>> W.crawl_1()
this is crawl 1
saving to database
>>> W.crawl_2()
this is crawl 2
saving to database
>>> W.this_is_not_wrapped()
this is not wrapped
>>>
你可以看到我们的save_to_database方法被调用后
crawl_1 和 crawl_2 中的每一个(但不是在 this_is_not_wrapped 之后)。
以上在 Python 2 中有效。在 Python 3 中,替换为:
class Wrapped (object):
__metaclass__ = Wrapper
与:
class Wrapped (object, metaclass=Wrapper):