闭包函数
闭包如何产生的?
因为函数内部又有嵌套函数,
嵌套函数定义:定义在内部的函数无法在全局被调用 所以产生了闭包问题def func1() def func2() a = 1 return a func2()
闭包产生的问题?
就是func1 拿不到func2 的变量a
怎么才能拿到呢? 我们知道,函数是第一类对象(第一类对象说白了你可以把函数当成变量使用),你可以把func1中的变量(func2)通过return返回def func1() def func2() a = 1 return a return func2x = func1() #这样就拿到了func2 并赋值给了变量xx() # x()等同于 func2() 看明白了吧 就得到了一个返回值a 这样就拿到func2 的变量a了
而如果:
def func1(para1): para1 def func2(): a = 1 return para1 + a return func2func1(5) #如果把5传给func1 就会把def func2 这个函数打包,
注意内部函数:
def func2(): a = 1 return 5 + a
func1(5)() #等同于func2()
就变相调用函数func2() 得到返回值 6
print(func1(5)()) # 6
如果func1(8), 那么func2打包后:
def func2() a = 1 return 8 + a
每次调用func1,就会返回(打包)一个新的闭包实例
所以:
闭包 = 函数 + 引用环境
闭包:python中的闭包从表现形式上定义(解释)为:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)
装饰器
装饰器函数:
装饰器函数本质 就是闭包的一种应用
装饰器功能目的 就是实现 不修改原函数及其调用方式的情况下对原函数功能进行扩展
def timmer(func): def inner(): print(1) func() #内部函数引用外部函数的参数变量 产生闭包函数 print(2) return innerdef func(): print('hello')timmer(func) #得到 inner函数名f = timmer(func) # f = innerf() # inner() # 1# hello# 2
应用中涉及到的函数:
被装饰函数
装饰函数 内嵌包装函数装饰器书写格式:
def wrapper(func): ------------装饰函数 def inner(*args,**kwargs): ------------内嵌包装函数 #功能添加(被装饰函数执行之前扩展的功能代码)(把这两行功能添加代码注释掉,等于去掉所有的装饰器) ret = func(*args,**kwargs) #功能添加(被装饰函数执行之后扩展的功能代码) return ret return inner
使用:
@wrapper #@wrapper 语法糖 等价于 func = wrapper(func) def func(): # 被装饰函数 return 1111 #带返回
装饰器 开放封闭原则:
1.对 扩展 开放 允许代码扩展、添加新功能。(修复 bug)
2.对 修改 封闭 修改函数,有可能牵一发动全身
小示例:一次登录,处处使用
flag = Truedef login(args): def inner(): global flag if flag: #第一次调用函数,进入登录,要输入用户名和密码 如果第一次调用函数用户名密码正确, flag为False,不用进入登录 username = input("Please enter your user name:") pwd = input("Please enter your password:") if username == 'kitty' and pwd == '123': print("Login successfully!") flag = False #用户名密码正确,就把条件改变, if not flag: #如果flag发生变化,说明登录成功,否则,就进不去if语句,执行不了args() args() return inner@login #语法糖 def article(): print("Welcome to article!")@logindef diary(): print("Welcome to diary!")article()diary()#Please enter your user name:kitty# Please enter your password:123# Login successfully!# Welcome to article!# Welcome to diary!
使用装饰器计算代码运行时间
import timeprint(time.time()) #1970年1月1日00:00:00:000开始计秒def timer(func): def inner(): start_time = time.time() time.sleep(0.1) func() end_time = time.time() print(end_time - start_time) return inner@timerdef func(): print(1111)func()
取消装饰器函数:
def outer(flag): def wrapper(func): def inner(): if flag: #falg = False 就不执行扩展功能 print("扩展功能") ret = func() if flag: ##falg = False 就不执行扩展功能 print("扩展功能") return ret return inner return wrapper@outer(False)#@outer(True)def func(): print('kitty')func()
多个装饰器装饰一个函数
def wrapper1(func): def inner(): print(111) func() print(222) return innerdef wrapper2(func): def inner(): print('aaa') func() print('bbb') return inner@wrapper2@wrapper1def func(): print('kitty')func()aaa# 111# kitty# 222# bbb