Python装饰器(函数)

闭包

1.作用域L_E_G_B(局部、内嵌、全局...):

1 x=10#全局
2 
3 def f():
4     a=5 #嵌套作用域
5     def inner():
6         count = 7 #局部变量
7         print a
8         return 1

从内往外寻找 a 。

2.高阶函数

a.函数名可以作为参数输入

b.函数名可以作为返回值

3.闭包

 1 def outer():
 2     x=10
 3     def inner(): #条件1 inner是内部函数
 4         print(x) #条件2 外部环境的一个变量
 5 
 6     return inner #结论: 内部函数inner就是一个闭包
 7 
 8 outer()()#调用inner
 9 #同上
10 f = outer()#获得inner
11 f()#调用执行inner
12 
13 #不能直接调用inner,因为inner为局部变量,全局无法调用

执行结果

10
10

Process finished with exit code 0

第10行,获得inner变量,第11行执行inner函数,而执行inner函数时(在外部执行),其中x变量既不属于inner函数内部变量,也不属于全局变量,按理应该报错却没报错,这种现象称为闭包。

定义:如果在一个内部函数里,对在外部作用域(但不是全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。

在内部函数里(inner函数中),对在外部作用域的变量(x)进行引用(print),那么内部函数(inner)就被认为是闭包。

装饰器

 1 import time
 2 
 3 def foo():
 4     print("foo.....")
 5     time.sleep(2)
 6 
 7 def bar():
 8     print("bar.....")
 9     time.sleep(3)
10 
11 def show_time(f): #函数名作参数
12     start = time.time()
13     f()
14     end = time.time()
15     print("spend %s" % (end - start))
16 
17 
18 show_time(bar)

函数名作参数,减少重复代码。

执行结果:

bar.....
spend 3.0022976398468018

Process finished with exit code 0

 但是以上方法改变了调用方式,加上所需时间功能后,不是直接用foo,而是用show_time,这样对所有使用foo函数的代码都需修改,违背了封闭开放原则。

 1 import time
 2 
 3 def foo():
 4     print("foo.....")
 5     time.sleep(2)
 6 
 7 def bar():
 8     print("bar.....")
 9     time.sleep(3)
10 
11 def show_time(f): #函数名作参数 ,装饰器
12     def inner():
13         start = time.time()
14         f()
15         end = time.time()
16         print("spend %s" % (end - start))
17     return inner
18 
19 foo = show_time(foo)
20 foo()

show_time即为装饰器,inner函数为闭包,f函数名变量即为外部作用域变量。

执行结果:

foo.....
spend 2.00213360786438

Process finished with exit code 0

但是以上方法还需要自己赋值,不够简便、优雅。

优雅的写法:

 1 import time
 2 
 3 def show_time(f): #函数名作参数 ,装饰器
 4     def inner():
 5         start = time.time()
 6         f()
 7         end = time.time()
 8         print("spend %s" % (end - start))
 9     return inner
10 
11 @show_time  #  foo = show_time(foo), 给foo函数添加一个计算所需时间的功能
12 def foo():
13     print("foo.....")
14     time.sleep(2)
15 
16 #foo = show_time(foo)
17 foo()

11行,给foo函数添加一个计算所需时间的功能,@show_time,可理解为foo = show_time(foo)

执行结果:

foo.....
spend 2.002133369445801

Process finished with exit code 0

 被装饰函数参数(功能函数加参数):

 1 import time
 2 
 3 def show_time(f): #函数名作参数 ,装饰器
 4     def inner(x, y):
 5         start = time.time()
 6         f(x, y)
 7         end = time.time()
 8         print("spend %s" % (end - start))
 9     return inner
10 
11 @show_time  #  add = show_time(add), 给add函数添加一个计算所需时间的功能
12 def add(a, b):
13     print(a + b)
14     time.sleep(1)
15 
16 #foo = show_time(foo)
17 add(1, 2)

执行结果:

3
spend 1.0010321140289307

Process finished with exit code 0

不定长参数:

 1 import time
 2 
 3 def show_time(f): #函数名作参数 ,装饰器
 4     def inner(*x, **y):
 5         start = time.time()
 6         f(*x, **y)
 7         end = time.time()
 8         print("spend %s" % (end - start))
 9     return inner
10 
11 @show_time
12 def add(*a, **b): # a为元组
13     sums = 0
14     for i in a:
15         sums += i
16     print(sums)
17     time.sleep(1)
18 
19 
20 add(1, 2, 5, 7, 9)#不定长参数

其中a为元组。

执行结果:

24
spend 1.0011086463928223

Process finished with exit code 0

装饰器参数:

 1 import time
 2 
 3 def logger(flag=''):#默认空
 4 
 5     def show_time(f):  # 函数名作参数 ,装饰器
 6         def inner(*x, **y):
 7             start = time.time()
 8             f(*x, **y)
 9             end = time.time()
10             print("spend %s" % (end - start))
11             if flag == 'true':
12                 print('日志记录')
13         return inner
14     return show_time
15 
16 def show_time(f): #函数名作参数 ,装饰器
17     def inner(*x, **y):
18         start = time.time()
19         f(*x, **y)
20         end = time.time()
21         print("spend %s" % (end - start))
22     return inner
23 
24 @logger('true') # 相当于@show_time,不过有了一个flag变量,相当于闭包
25 def add(*a, **b): # a为元组
26     sums = 0
27     for i in a:
28         sums += i
29     print(sums)
30     time.sleep(1)
31 
33 add(1, 2, 5, 7, 9)#不定长参数
34 
35 @logger()
36 def bar():
37     print("bar......")
38     time.sleep(3)
39 
40 bar()

装饰器加参数flag,决定是否输出日志,此时show_time为闭包。

执行结果:

24
spend 1.001152515411377
日志记录
bar......
spend 3.00311541557312
原文地址:https://www.cnblogs.com/112358nizhipeng/p/9471695.html