闭包
简单认识一下闭包
以下代码,内层inner函数不仅依赖于自身的参数b,还依赖于外层outer函数的参数a。inner就是一个闭包函数,既能访问外部变量,又保证外部变量不是全局的,不会被篡改掉,确保了外部变量的安全。
def outer(a):
def inner(b):
print(f"<{a}>{b}<{a}>")
return inner
n1 = outer('程序员') # n1的类型是一个函数
n1('学习python')
n1('学习java')
n2 = outer('软件测试工程师')
n2('功能测试')
n2('自动化测试')
如果要在内层函数修改外层函数的变量,需要用nonlocal
修饰,示例代码如下:
def outer(num1):
def inner(num2):
# 要对外层num1进行修改的话,需要nonlocal修饰
nonlocal num1
num1 += num2
print(num1)
return inner
fn = outer(10)
fn(5)
# 输出为15
案例:使用闭包方式简单实现ATM存取款
def account_create(initial_amount=0):
def atm(num, deposit=True):
nonlocal initial_amount
if deposit:
initial_amount += num
print(f"存款:+{num},账户余额:{initial_amount}")
else:
if initial_amount<num:
print(f"钱不够{num}了,取不出来!")
else:
initial_amount -= num
print(f"取款:-{num},账户余额:{initial_amount}")
return atm
atm = account_create()
atm(100, deposit=True)
atm(500, deposit=True)
atm(200, deposit=False)
atm(1000, deposit=False)
闭包的优缺点:
优点:
无需定义全局变量即可实现通过函数,持续的访问、修改某个值
闭包使用的变量位于在函数内,难以被错误的调用修改
缺点:
由于内部函数持续引用外部函数的值,所以会导致这一部分内存空间不被释放,一直占用内存
装饰器
装饰器其实也是一种闭包,其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能。
示例代码1:
def outer(func):
def inner():
print("我要睡觉了......")
func()
print("睡醒了,我要起床了......")
return inner()
@outer # 相当于给sleep增加outer的装饰器
def sleep():
import random
import time
print("睡眠中......")
time.sleep(random.randint(1, 5))
sleep()
示例代码2:
(1)代码实现:统计一个函数的运行时间:
import time
# 统计一个函数的运行时间
def timer(func):
def gf():
start_time = time.time()
func()
end_time = time.time()
print("func运行的时间为:", end_time - start_time)
return gf
@timer
def foo():
time.sleep(3)
print("in foo")
foo()
(2)被装饰函数带参数
import time
# 统计一个函数的运行时间
def timer(func):
def gf(*args, **kwargs):
start_time = time.time()
func(*args, **kwargs)
end_time = time.time()
print("func运行的时间为:", end_time - start_time)
return gf
@timer
def foo(name, age):
time.sleep(3)
pri