裝飾器是一個很著名的設計模式,經常被用于有切面需求的場景,較為經典的有插入日志、性能測試、事務處理等。
裝飾器其實就是一個工廠函數,它接受一個函數為參數,然後傳回一個新函數,其閉包中包含了原函數
1、簡單裝飾器:
def deco(func):
def wrapper():
print "start"
func() #調用函數
print "end"
return wrapper
@deco
def myfun():
print "run"
myfun()
由于裝飾器函數傳回的是原函數的閉包wrapper,實際上被裝飾後的函數就是wrapper,其運作方式就和wrapper一樣。相當于:
myfun=deco(myfun)
2、裝飾任意參數的函數:
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
3、帶參數的裝飾器
裝飾器接受一個函數作為參數,這個毋庸置疑。但是有時候我們需要裝飾器接受另外的參數。此時需要再加一層函數,實際上是定義了一個生成裝飾器的工廠函數,調用它,搭配需要的參數,來傳回合适的裝飾器
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)
4、裝飾器帶類參數
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()
5、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}) #使用者名渲染到前端頁面
轉載于:https://www.cnblogs.com/honey-badger/p/8978168.html