在python语言中“装饰器”模式被设计成语言内置的设计模式,使得使用该模式变得简单,仅仅需要在目标函数前使用‘@’符号加装饰器名就能达到目的。但如果同一个目标函数需要进行多次装饰,那么调用目标函数时装饰器的执行顺序是怎样的呢?
这里有个例子,有个目标函数叫lunch,中午调用一下来决定午饭吃什么
# coding: utf-8
import random
# 饭馆
restaurants = {
'KFC': ['hamburger', 'chicken wings', 'ice cream', 'salmon fish'],
'xiapu': ['Beef hotpot', 'Mutton hotpot', 'Tomato hotpot'],
}
def chose_food(f):
print 'decorator: chose_food enter'
def func(*args, **kwargs):
print 'decorator: chose_food::func enter'
a_rstrnt = args[0]
food = random.choice(restaurants[a_rstrnt])
return f(food, *args, **kwargs)
print 'decorator: chose_food exit'
return func
def restaurant(f):
print 'decorator: restaurant enter'
def func(*args, **kwargs):
print 'decorator: restaurant::func enter'
a_rstrnt = random.choice(restaurants.keys())
return f(a_rstrnt, *args, **kwargs)
print 'decorator: restaurant exit'
return func
@restaurant
@chose_food
def lunch(food, addr, then):
print "We're going to {} for '{}', then {}".format(addr, food, then)
lunch('have a rest')
输出结果
decorator: chose_food enter
decorator: chose_food exit
decorator: restaurant enter
decorator: restaurant exit
decorator: restaurant::func enter
decorator: chose_food::func enter
We're going to KFC for 'hamburger', then have a rest
通过打印结果可以看出装饰器装饰的顺序是“从下到上”依次执行,而执行的顺序是“从上到下”。
原因是装饰器在这个例子中起的作用是对目标函数包装,两个装饰器装饰过后,是这种情形:
lunch(then){} = deco.restaurant(then) {
deco:chose_food(rstrnt, then) {
lunch(food, rstrnt, then){}
}
}
lunch(then)
被调用时自然按照由外到内的顺序执行。
网友评论