1. 介绍闭包
闭包:如果在一个内部函数里,对在外部作用域的变量(不是全局作用域)进行引用,那边内部函数被称为闭包(closure)
例如:如果在一个内部函数里:func2()就是内部函数,
对在外部作用域的变量进行引用:n就是被引用的遍历,n在外部作用域func里面被定义,而不是全局作用域
1 def func():
2 n = 10
3 def func2():
4 print('func2', n)
5 return func2
6
7 f = func()
8 f()
9
2. 介绍装饰器
装饰器:本质上是一个闭包函数。
功能:在不修改原函数的及其调用方式的情况下对原函数进行功能扩展。这个特点正好满足软件开发原则:开放封闭原则
练习:请设计一个decorator,它可作用于任何函数上,并打印该函数的执行时间:
1 import time
2 import functools
3
4 def metric(fn):
5 @functools.wraps(fn)
6 def wrapper(*args, **kwargs):
7 start = time.time()
8 ret = fn(*args, **kwargs)
9 end = time.time()
10 print('%s executed in %s ms' % (fn.__name__, end - start))
11 return ret
12 return wrapper
13
14 @metric
15 def fast(x, y):
16 time.sleep(0.0012)
17 return x + y
18
19 @metric
20 def slow(x, y, z):
21 time.sleep(0.1234)
22 return x * y * z
23
24 f = fast(11, 22)
25 s = slow(11, 22, 33)
26 if f != 33:
27 print('测试失败!')
28 elif s != 7986:
29 print('测试失败!')
3. 运用装饰器遵循开放封闭原则
开放:对拓展是开放的
为什么要对扩展开放呢?
我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。
封闭:对修改是封闭的
为什么要对修改封闭呢?
就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。
装饰器完美的遵循了这个开放封闭原则。
例子:拷贝alex的网站登录
1 login_status = False
2 def login(func):
3 def login_inner(*args, **kwargs):
4 _user = 'alex'
5 _pwd = 'abc123'
6 global login_status
7 if login_status == False:
8 user = input('User Name:')
9 password = input('Password:')
10 if user == _user and password == _pwd:
11 login_status = True
12 print('成功登录...')
13 else:
14 print('用户名和密码错误')
15 else:
16 print('用户已经登录,验证通过')
17 if login_status:
18 func(*args, **kwargs)
19 return login_inner
20
21 def home():
22 print('---首页---')
23 def henan():
24 print('---河南专区---')
25 @login
26 def hebei(type):
27 print('---河北专区---', type)
28 hebei = login(hebei)
29 hebei("3p")