Day5 python基础5 装饰器

 一、python装饰器基本概念 

  定义:本质是函数,用来装饰其他函数,即为其他函数添加附加功能。

  原则:1.不能修改被装饰函数的源代码;

       2.不能修改被装饰函数的调用方式。

  实现装饰器的知识储备:

    1.函数即“变量”。

    2.高阶函数

      a.把一个函数名当作实参传给另一个函数;

      b.返回值中包含函数名

    3.嵌套函数

      即在用def定义一个函数的函数体中再用def定义函数。

  高阶函数 + 嵌套函数 => 装饰器

  二、函数即“变量” 

  定义一个变量

1 x = 1

  变量名x相当于一个门牌号,而1就是这个门牌号所指房间中的内容。

  定义一个函数

1 def foo():
2     print('in the foo')

  函数名foo就相当于一个门牌号,而函数体 print('in the foo') 作为一串字符串存在这个门牌号所指的房间中。

  故 函数即“变量”

 三、高阶函数 

  a. 把一个函数名当作实参传递给另一个函数(在不修改被装饰函数源代码的情况下为其添加功能);

  b. 返回值中包含函数名(不改变函数的调用方式)。

  代码示例:

 1 #a:把一个 函数名 当作实参传给另一个函数 (在不修改被装饰函数源代码的情况下为其添加功能)
 2 import time
 3 
 4 def bar():
 5     time.sleep(3)
 6     print('in the bar')
 7 
 8 def test1(func):
 9     print(func)
10     start_time = time.time()
11     func()     #运行bar()
12     stop_time = time.time()
13     print("the func run time is %s"%(stop_time-start_time))
14 
15 test1(bar)  # bar即为函数的内存地址,加“()”即为调用此函数
16 #bar()
<function bar at 0x0000021F3E956048>
in the bar
the func run time is 3.0008294582366943
Result

 

 1 #b:返回值中包含 函数名 (不改变函数的调用方式)
 2 import time
 3 
 4 def bar():
 5     time.sleep(3)
 6     print('in the bar')
 7 
 8 def test2(func):
 9     print(func)
10     return func
11 
12 t = test2(bar)
13 print(t)
14 bar = test2(bar)   # 注意这一句
15 bar()
16 t()   #run bar
<function bar at 0x00000265D5486048>
<function bar at 0x00000265D5486048>
<function bar at 0x00000265D5486048>
in the bar
in the bar
Result

 四、嵌套函数 

  在用def定义一个函数的函数体中再用def定义函数。

  代码示例:

1 def foo():
2     print("in the foo")
3     def bar():
4         print("in the bar")
5     bar()
6 #bar()       #错误写法 ,函数即变量,可把bar看作局部变量
7 foo()
in the foo
in the bar
Result

 五、装饰器 

  1. 引例,为test1()增加输出运行时间的功能。

 1 import time
 2 
 3 def timer(func):   #timmer(test1)    func=test1
 4     def deco():
 5         start_time = time.time()
 6         func()     #在def中,func()只是一串字符串,func()并没有调用执行
 7         stop_time = time.time()
 8         print("the func run time is %s" % (stop_time - start_time))
 9     return deco
10 
11 def test1():
12     time.sleep(3)
13     print("in the test1")
14 
15 test1 = timer(test1)  #注意这一句
16 test1()    #运行test()即为运行deco()
in the test1
the func run time is 3.0002777576446533
Result

  2.无参数装饰器

import time

def timer(func):   #timmer(test1)    func=test1
    def deco():
        start_time = time.time()
        func()     #在def中,func()只是一串字符串,func()并没有调用执行
        stop_time = time.time()
        print("the func run time is %s" % (stop_time - start_time))
    return deco

@timer   # test1=timer(test1)
def test1():
    time.sleep(3)
    print("in the test1")

test1()
in the test1
the func run time is 3.0149574279785156
Result

  引入 @timer ,即相当于 test1=timer(test1) 语句。

  3.带不确定个数个参数的装饰器

 1 import time
 2 
 3 def timer(func):   #timmer(test1)    func=test1
 4     def deco(*args,**kwargs):
 5         start_time = time.time()
 6         func(*args,**kwargs)     #在def中,func()只是一串字符串,func()并没有调用执行
 7         stop_time = time.time()
 8         print("the func run time is %s" % (stop_time - start_time))
 9     return deco
10 
11 @timer   # test1=timer(test1)
12 def test1():
13     time.sleep(3)
14     print("in the test1")
15 
16 @timer
17 def test2(name):
18     time.sleep(1)
19     print("in the test2",name)
20 
21 test1()
22 test2('ztian')
in the test1
the func run time is 3.000495195388794
in the test2 ztian
the func run time is 1.000511884689331
Result

  利用*args和**kwargs实现不定参数个数的装饰器。

   4.被装饰函数带返回值

 1 import time
 2 
 3 def timer(func):   #timmer(test1)    func=test1
 4     def deco(*args,**kwargs):
 5         start_time = time.time()
 6         res = func(*args,**kwargs)     #在def中,func()只是一串字符串,func()并没有调用执行
 7         stop_time = time.time()
 8         print("the func run time is %s" % (stop_time - start_time))
 9         return res
10     return deco
11 
12 @timer   # test1=timer(test1)
13 def test1():
14     time.sleep(3)
15     print("in the test1")
16     return "the return of test1"
17 
18 print(test1())
in the test1
the func run time is 3.0094504356384277
the return of test1
Result

   5.装饰器终极版

  三层嵌套函数,使装饰器可以对应于不同的类型。

  代码示例(模拟网站登录验证,可采用本地或ldap的验证方式):

 1 user,passwd = 'ztian','abc123'
 2 
 3 def auth(auth_type):                # auth_type <- "local"
 4     print("auth func->",auth_type)
 5     def outer_wrapper(func):        # func <- home
 6         print("outer_wrapper func->",func)
 7 
 8         def wrapper(*args,**kwargs):
 9             print("wrapper func->", *args,**kwargs)
10             if auth_type == "local":
11                 username = input("Username:").strip()
12                 password = input("Password:").strip()
13                 if user==username and passwd==password:
14                     print("\033[32;1mUser has passed authentication\033[0m")
15                     res = func(*args,**kwargs)
16                     print("after authentication".center(50,'-'))
17                     return res
18                 else:
19                     exit("\033[31;1mInvaild username or password\033[0m")
20             elif auth_type == "ldap":
21                 print("no ldap")
22 
23         return wrapper
24     return outer_wrapper
25 
26 def index():
27     print("welcome to index page")
28 
29 @auth(auth_type = "local")    # 先将auth_type传过去,然后home = out_wrapper(home)将home传给func
30 def home():
31     print("welcome to home page")
32     return "from home"
33 
34 @auth(auth_type = "ldap")
35 def bbs():
36     print("welcome to bbs page")
37 
38 index()
39 print(home())   #wrapper()
40 bbs()
outer_wrapper func-> <function home at 0x000001F00D2AD6A8>
auth func-> ldap
outer_wrapper func-> <function bbs at 0x000001F00D2AD620>
welcome to index page
wrapper func->
Username:ztian
Password:abc123
User has passed authentication
welcome to home page
---------------after authentication---------------
from home
wrapper func->
no ldap
Result

 

posted @ 2018-02-04 22:40  挤成肉夹馍  阅读(132)  评论(0编辑  收藏  举报