标签:bbs 不同 认证方式 password 类对象 new view imp 代码
def func(): return "hello,world" ref1 = func # 将函数对象赋值给ref1 , type(ref1)是 function ref2 = func() # 函数调用, type(ref2) 是 string
定义:装饰器的“器“就是函数,基本语法用def 来定义,本质就是函数,其功能是装饰其他函数,为其他函数添加附加功能
原则:装饰器对被装饰函数完全透明
结构:高阶函数 + 嵌套函数;
总结下, 装饰器就是一个返回值为函数的高阶函数,其中至少嵌套一个函数(作为返回值返回)
工作原理:Func = Deco(Func) 用语法糖 syntax suger来表示@
第一步: 被装饰的函数作为参数传递给装饰器函数,并执行装饰器函数, 返回值记作Newfunc
第二步: 原函数重新赋值为Newfunc
1 #!user/bin/env python 2 # -*- coding:utf-8 -*- 3 4 import time 5 6 7 def timer(func): # timer(test1), 将test1的内存地址传给func; 其实最终通过return返回deco的内存地址 8 def deco(): 9 start_time = time.time() 10 func() 11 stop_time = time.time() 12 print(‘the func run time is %s‘ %(stop_time-start_time)) 13 return deco # 直接返回deco函数的内存地址,如此下面test1 = deco(test1),如此test1()就可以正常调用 14 15 16 @timer # 就是一步运行工作,等于test1 = timer(test1) 注意此处不能加括号,因为装饰的函数,而test1()是一个返回值 17 def test1(): 18 time.sleep(3) 19 print(‘in the test1‘) 20 21 22 test1() # 此时test1 执行的是deco的内存地址,因为timer函数中的return deco 23 print(test1) # 被装饰过的test1的内存地址返回: <function timer.<locals>.deco at 0x00000244D3824048>
逻辑解释
起始行 | 结束行 | 代码 | 解释 |
- | 4 | import time | 导入time模块 |
4 | 7 | def timer(func) | timer(test1), 将test1的内存地址闯入func, 最终return deco 的内存地址 |
7 | 16 | @timer |
直接跳到语法糖,执行timer装饰器 表示: test1 = timer(test1) |
16 | 8 | def deco() | |
8 | 13 | return deco | 返回值是deco的内存地址 |
13 | 22 | test1() | 调用test1(),经过@timer的重新赋值,此时执行的是deco的内存地址,最终调用deco() |
22 | 9 | start_time = time.time() | 执行deco() |
9 | 10 | func() | 在deco函数内部,开始调用变量func, 此时,func即test1(), |
10 | 18 | time.sleep(3) | 执行原test1() |
18 | 19 | print(‘in the test1) | |
19 | 11 | stop_time = time.time() | |
11 | 12 | print(‘run time = %s‘ %(stop_time - start_time) |
核心是内存地址的转移。
#!user/bin/env python # -*- coding:utf-8 -*- import time def timer(func): # 将test2的内存地址传给func def deco(*args,**kwargs): # 用非固定参数*args, **kwargs;如此满足有参数,和没有参数的被装饰函数 start_time = time.time() func(*args,**kwargs) stop_time = time.time() print(‘the func run time is %s‘ %(stop_time-start_time)) return deco # 直接返回deco函数的内存地址 @timer # test2 = timer(test2)= deco; test2() = deco(); 所以当test2有函数变量,deco也需要加函数变量。 def test2(name): # test2本身带参数 time.sleep(3) print(‘in the test2‘) test2(‘alex‘)
在这种情况下,
1 #!user/bin/env python 2 # -*- coding:utf-8 -*- 3 4 user,passwd = ‘alex‘,‘abc123‘ 5 6 def auth(func): 7 def wrapper(*args,**kwargs): 8 username = input(‘Username‘).strip() 9 password = input(‘Password‘).strip() 10 11 if user == username and passwd == password: 12 print("\033[32;1mUser has passed authorization\033[0m") 13 res = func(*args,**kwargs) # 赋值 14 return res # 返回res 15 else: 16 exit(‘\033[31;1mInvalid username or password\033[0m‘) 17 return wrapper # 返回wrapper的内存地址 18 19 @auth(auth_type="local") 20 def home(): 21 print(‘welcome to home page‘) 22 return "from home" 23 24 print(home()) #打印返回from home
1 #!user/bin/env python 2 # -*- coding:utf-8 -*- 3 4 # 例三:带参数的装饰器(终结版装饰器) 5 # 情景要求: 配用多种认证方式。 home()认证方式用本地local认证,bbs()用远程的ldap 6 7 user,passwd = ‘alex‘,‘abc123‘ 8 9 10 def auth(auth_type): # home()的can 11 def outer_wrapper(func): 12 def wrapper(*args,**kwargs): 13 username = input(‘Username‘).strip() 14 password = input(‘Password‘).strip() 15 16 if user == username and passwd == password: 17 print("\033[32;1mUser has passed authorization\033[0m") 18 res = func(*args,**kwargs) # 赋值 19 return res # 返回res 20 else: 21 exit(‘\033[31;1mInvalid username or password\033[0m‘) 22 return wrapper # 返回wrapper的内存地址 23 return outer_wrapper 24 25 def index(): 26 print(‘welcome to index page‘) 27 28 29 @auth(auth_type="local") 30 def home(): 31 print(‘welcome to home page‘) 32 return "from home" 33 34 home() 35 36 @auth(auth_type="ldap") 37 def bbs(): 38 print(‘welcome to bbs page‘) 39 40 bbs()
“Python 里为什么函数可以返回一个函数内部定义的函数?”, https://www.zhihu.com/question/25950466/answer/31731502
“12步轻松搞定python装饰器”,http://python.jobbole.com/81683/
Python 基础 - Day 4 Learning Note - Decorator 装饰器
标签:bbs 不同 认证方式 password 类对象 new view imp 代码
原文地址:http://www.cnblogs.com/lg100lg100/p/7241601.html