標籤:
裝飾器的本質:
當你在用某個@decorator來修飾某個函數func時,如下所示:
@decoratordef func(): pass
其解譯器會解釋成下面這樣的語句:
func=decorator(func)
本質是把一個函數當作參數傳遞到另一個函數中,然後再調用。
def hello(fn): def wrapper(): print "hello,%s" %fn.__name__ fn() print "goodbye,%s" %fn.__name__ return wrapper@hellodef foo(): print "I am foo">>>foo()"hello,foo""I am foo""goodbye,foo"
hello(foo)返回了wrapper()函數,所以foo其實變成了wrapper的一個變數,而後面的foo()執行其實變成了wrapper()
多個裝飾器:
@decorator_one@decorator_twodef func(): pass
相當於func=decorator_one(decorator_two(func))
帶參數的裝飾器:
@decorator(arg1,arg2)def func(): pass
相當於func=decorator(arg1,arg2)(func).這意味著decorator(arg1,arg2)這個函數需要返回一個“真正的裝飾器”。
def mydecorator(arg1,arg2): def _mydecorator1(func): def _mydecorator2(*args,**kw): res=func(*args,**kw) return res return _mydecorator2 return _mydecorator1
上面的函數返回的_mydecorator1才是真正的裝飾器。因此,當裝飾器需要參數時,必須使用第二集封裝。因為裝飾器在模組第一次被讀取時由解釋程式裝入,所以它們的使用必須受限於總體上可以應用的封裝器。
帶參數及多個裝飾器:
def makeHtmlTag(tag,*args,**kwds): def real_decorator(fn): css_class="class=‘{0}‘".format(kwds["css_class"]) if "css_class" in kwds else "" def wrapped(*args,**kwds): return "<"+tag+css_class+">"+fn(*args,**kwds)+"</"+tag+">" return warpped(*args,**kwds) return real_decorator
@makeHtmlTag(tag=‘i‘,css_class=‘italic_css‘)@makeHtmlTag(tag=‘b‘,css_class=‘bold_css‘)def hello(): return "hello world">>>hello()<i class=‘italic_css‘><b class=‘bold_css‘>hello world</b></i>
class式裝飾器:
class mydecorator(object): def __init__(self,fn): print "inside mydecorator--init" self.fn=fn def __call__(self): self.fn() print "inside mydecorator--call"@mydecoratordef myfunc(): print "inside myfunc">>>myfunc"inside mydecorator--init""inside myfunc""inside mydecorator--call"
重寫makeHtmlTag代碼:
python中的裝飾器