裝飾器是一個很著名的設計模式,常常被用於有切面需求的場景,較爲經典的有插入日誌、性能測試、事務處理等。
裝飾器其實就是一個工廠函數,它接受一個函數爲參數,而後返回一個新函數,其閉包中包含了原函數html
一、簡單裝飾器:前端
def deco(func): def wrapper(): print "start" func() #調用函數 print "end" return wrapper @deco def myfun(): print "run" myfun()
因爲裝飾器函數返回的是原函數的閉包wrapper,實際上被裝飾後的函數就是wrapper,其運行方式就和wrapper同樣。至關於:
myfun=deco(myfun)python
二、裝飾任意參數的函數:django
def deco(func): def warpper(*args,**kw): print "start" func(*args,**kw) print "end" return warpper @deco def myfun1(param1): print "run with param %s"%(param1) @deco def myfun2(param1,param2): print "run with param %s and %s"%(param1,param2) myfun1("something") myfun2("something","otherthing") # start # run with param something # end # start # run with param something and otherthing # end
三、帶參數的裝飾器設計模式
裝飾器接受一個函數做爲參數,這個毋庸置疑。可是有時候咱們須要裝飾器接受另外的參數。此時須要再加一層函數,其實是定義了一個生成裝飾器的工廠函數,調用它,搭配須要的參數,來返回合適的裝飾器session
def log(text): def deco(func): def wrapper(*args,**kw): print text func(*args,**kw) print text + " again" return wrapper return deco @log("hello") def myfun(message): print message myfun("world") # hello # world # hello again
log=log("hello"),把返回的deco函數賦值給log,此時log至關於其包含text=「hello」的閉包
myfun=log(myfun),至關於把myfun傳入了deco函數,而且返回wrapper,並賦值給myfun,此時myfun至關於其裝飾後的閉包。
總體來看是myfun=log("hello")(myfun)閉包
四、裝飾器帶類參數app
class locker: def __init__(self): print("locker.__init__() should be not called.") @staticmethod def acquire(): print("locker.acquire() called.(這是靜態方法)") @staticmethod def release(): print(" locker.release() called.(不須要對象實例)") def deco(cls): '''''cls 必須實現acquire和release靜態方法''' def _deco(func): def __deco(): print("before %s called [%s]." % (func.__name__, cls)) cls.acquire() try: return func() finally: cls.release() return __deco return _deco @deco(locker) def myfunc(): print(" myfunc() called.") myfunc() myfunc()
五、django自定義裝飾器實現登陸驗證函數
def Check_Login(func): #自定義登陸驗證裝飾器 def warpper(request,*args,**kwargs): is_login = request.session.get('IS_LOGIN', False) if is_login: func(request,*args,**kwargs) else: return HttpResponseRedirect("/polls/login_user") return warpper def login_user(request): if request.method == 'POST': form = LoginForm(request.POST) if form.is_valid(): all_data = form.clean() #獲取post數據,例如 {'username': u'yang1', 'password': 111} exist = User.objects.filter(username = all_data['Form_username'],password = all_data['Form_password']).first() if exist: request.session['IS_LOGIN'] = True #設置session的隨機字段值 request.session['uname'] = exist.username #設置uname字段爲登陸用戶 return HttpResponseRedirect('/polls/home') else: return HttpResponse("帳戶或密碼錯誤") else: form = LoginForm() return render(request, 'polls/login_user.html', {'form': form}) @Check_Login def home(request): username = request.session.get('uname', False) #獲取登陸用戶名 return render(request, 'polls/home.html', {'username': username}) #用戶名渲染到前端頁面