Python Decorator装饰器[转载]

1.能墙的可以直接看视频:https://www.youtube.com/watch?v=QqRvteWBSWg

2.场景: 

当一个函数中,不同逻辑混杂在一起的时候,程序的可读性会大打折扣。这个时候,可以考虑用一种叫做“装饰器”的东西来重新整理代码。这个例子简单介绍了python中装饰器的用法,遇到传参应该怎么办。

3.Code

3.1 打印10000内的质数

 1 def is_prime(num):
 2     if num <2:
 3         return False
 4     elif num ==2:
 5         return True
 6     else:
 7         for i in range(2,num):
 8             if num%i ==0:
 9                 return False
10         return True
11 
12 def prime_nums():
13     for i in range(2,10000):
14         if is_prime(i):
15             print i
16 
17 prime_nums()

3.2 加打印前后的耗时

此函数代码中既包含了逻辑的部分,又包含了计时部分,可读性很差。

想想如果还有一堆类似的函数[也需要计时,]就需要把逻辑和计时分开,用装饰器来实现。

import time
def is_prime(num):
    if num <2:
        return False
    elif num ==2:
        return True
    else:
        for i in range(2,num):
            if num%i ==0:
                return False
        return True

def prime_nums():
    t1 = time.time()
    for i in range(2,10000):
        if is_prime(i):
            print i
    t2 = time.time()
    print(t2-t1)
prime_nums()

3.3 装饰器函数的定义和运用

@声明

@运行26行时,运行的实际是装饰器函数

输出同3.2. 

 1 import time
 2 
 3 def display_time(func):
 4     def wrapper():
 5         t1 = time.time()
 6         func()
 7         t2 = time.time()
 8         print(t2 - t1)
 9     return wrapper
10 
11 def is_prime(num):
12     if num <2:
13         return False
14     elif num ==2:
15         return True
16     else:
17         for i in range(2,num):
18             if num%i ==0:
19                 return False
20         return True
21 
22 
23 @display_time
24 def prime_nums():
25     for i in range(2,10000):
26         if is_prime(i):
27             print i
28 prime_nums()   #实际运行此函数,运行的是装饰器函数


至此装饰器基本介绍完毕。

3.4 扩展

加需求:统计下10000内一共有多少个质数?   

#只在函数中加count 计数并没有,因为运行装饰器函数时,并未传给装饰器.

 1 import time
 2 
 3 def display_time(func):
 4     def wrapper():
 5         t1 = time.time()
 6         func()
 7         t2 = time.time()
 8         print(t2 - t1)
 9     return wrapper
10 
11 def is_prime(num):
12     if num <2:
13         return False
14     elif num ==2:
15         return True
16     else:
17         for i in range(2,num):
18             if num%i ==0:
19                 return False
20         return True
21 
22 
23 @display_time
24 def count_prime_nums():
25     count =0
26     for i in range(2,10000):
27         if is_prime(i):
28             #print i
29             count =count +1
30     return count
31 
32 count = count_prime_nums
33 print count

#解决方案:

在wrapper 函数里面把返回值结果用变量result记录下来

 1 import time
 2 
 3 def display_time(func):
 4     def wrapper():
 5         t1 = time.time()
 6         result =func()
 7         t2 = time.time()
 8         #print(t2 - t1)
 9         print "Total time:{:.5} s".format(t2-t1)
10         return result
11     return wrapper
12 
13 def is_prime(num):
14     if num <2:
15         return False
16     elif num ==2:
17         return True
18     else:
19         for i in range(2,num):
20             if num%i ==0:
21                 return False
22         return True
23 
24 
25 @display_time
26 def count_prime_nums():
27     count =0
28     for i in range(2,10000):
29         if is_prime(i):
30             #print i
31             count =count +1
32     return count
33 
34 count = count_prime_nums
35 print count

 

输出结果OK:

C:\Python27\python.exe C:/Git/Flask/me/decorator.py
Total time:0.553 s
1229

Process finished with exit code 0

3.5 扩展:如果被调用函数有参数怎么传参到装饰器?-----> 装饰器中加(*args)

   如下10000->maxnum:

@display_time
def count_prime_nums(): ====》def count_prime_nums(maxnum):

汇总:
装饰器关键点:
a.首先装饰器要有一个内部定义的函数(名字不一定wrapper,可以随便起)
b.自定义函数一定要返回要调用(装饰)的函数.[如下line 10]
 1 # -*- coding: UTF-8 -*-
 2 #refer to https://www.youtube.com/watch?v=QqRvteWBSWg
 3 import time
 4 def display_time(func):
 5     def wrapper(*args): # wrapper <-maxnum . *args: 可以有任意个参数
 6         t1 = time.time()
 7         result = func(*args)
 8         t2 = time.time()
 9         #print(t2 - t1)
10         print "Total time:{:.5} s".format(t2-t1)
11         return result # 必须返回被调用(装饰)函数
12     return wrapper
13 
14 def is_prime(num):
15     if num <2:
16         return False
17     elif num ==2:
18         return True
19     else:
20         for i in range(2,num):
21             if num%i ==0:
22                 return False
23         return True
24 
25 
26 @display_time
27 def count_prime_nums(maxnum):
28     count =0
29     for i in range(2,maxnum):
30         if is_prime(i):
31             #print i
32             count =count +1
33     return count
34 
35 count = count_prime_nums(20000)
36 print count

 

输出结果:

 

[注]视频转载:https://www.youtube.com/watch?v=QqRvteWBSWg

 

posted @ 2019-04-03 10:14  浪淘砂  阅读(91)  评论(0)    收藏  举报