函数--闭包和装饰器
一 闭包函数
一 什么是闭包?
#内部函数对外部作用域而非全局作用的引用,切记而非全局作用域(如:全局名称空间,和内置名称空间,都是属于全局作用域)
#提示:之前我们都是通过将外部的值传给函数,闭包提供了另外一种思路,包起来,包起来
def counter():
n=0
def incr():
nonlocal n
x=n
n+=1
return x
return incr
c=counter()
print(c())
print(c())
print(c())
print(c.__closure__[0].cell_contents) #查看闭包的元素
二 闭包的意义与应用
#闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域 #应用领域:延迟计算(原来我们是传参,现在我们是包起来) from urllib.request import urlopen def index(url): def get(): return urlopen(url).read() return get baidu=index('http://www.baidu.com') print(baidu().decode('utf-8'))
三:了解关键词
一 global global关键字用来在函数或其他局部作用域中使用全局变量。但是如果不修改全局变量也可以不使用global关键字。
gcount = 0
def global_test():
print (gcount)
def global_counter():
global gcount
gcount +=1
return gcount
def global_counter_test():
print(global_counter())
print(global_counter())
print(global_counter())
二 nonlocal
nonlocal关键字用来在函数或其他作用域中使用外层(非全局)变量。
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
def make_counter_test():
mc = make_counter()
print(mc())
print(mc())
print(mc())
四:重要 装饰器
装饰器就是闭包函数的一种应用场景
#前面所有的知识,都是为装饰器打基础
1. 为何要用装饰器、
#开放封闭原则:对修改的封闭,对扩展开放#1.开放封闭原则,对扩展是开放的,对修改是封闭的
#如:在公司一旦项目上线以后,会有扩展功能的场景,进行版本升级更新,假设你定义了一堆函数,对扩展开放指的是,你应该留出扩展的可能性,对修改封闭(不能修改源代码,函数的定义阶段,源代码不能动,调用阶段,调用方式不能动),
要找到一种方式,不修改函数的源代码,以及函数的调用的方式,为这个函数添加一个新功能。装饰器要遵循的就是这个原则
2.什么是装饰器
装饰器是他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用的对象。
强调装饰器的原则:1.不修改 被装饰器 的源代码, 2.不修改被装饰器对象的调用方式
装饰器的目的:在遵循1 和 2 前提下,为被装饰对象添加新功能
装饰器是——》函数, 被装饰器--》函数
#以下是定义的的index函数,需求:为index函数增加一个统计时间的功能,原来的功能不能动,先不考使用虑装饰器,实现统计时间的功能
import time
def index():
time.sleep(3)
print('welcome to index')
start = time.time()
#以上是被装饰对象,实现增加功能如下:
import time
def index():
time.sleep(3)
print('welcome to index')
start = time.time()
index()
stop = time.time()
print('run time is %s'%(stop - start))
#函数的功能没有改变,还在基础上实现了一个统计的功能,问题是这个功能只能统计index函数的,如果我换一个函数,home函数,那么就需要重新写代码进行统计。
#在这里是单独统计index的功能,如果想实现统计其他函数的时间,那么我们可以定义一个函数,实现统计其他函数的功能如下:
实现一:不使用装饰器实现
import time
def index():
time.sleep(3)
print('welcome to index')
def timmer():
start = time.time()
index()
stop = time.time()
print('run time is %s'%(stop - start))
#这样写的话,调用方式改变,函数就被定死了,只能统计index函数,那么我们需要想办法实现可以统计其他函数的时间,函数体代码需要一个参数,那就加一个参数如下:
#实现二: 不使用装饰器实现,通过函数实现所有函数统计时间功能
import time
def index():
time.sleep(3)
print('welcome to index')
def timmer(fun): #这里定义个统计时间的函数,fun参数
start = time.time()
fun()
stop = time.time()
print('run time is %s'%(stop - start))
timmer(index)
#在换一个home函数进行统计时间如下:
import time
def index():
time.sleep(3)
print('welcome to index')
def home():
time.sleep(3)
print('welcome to home')
def timmer(fun):
start = time.time()
fun()
stop = time.time()
print('run time is %s'%(stop - start))
timmer(home)
#返回结果如下:
welcome to home
run time is 3.001171350479126
#在这里我们给timmer函数加一个fun参数,实现统计所有函数时间的功能,需求我们实现了,但是调用方式改变了。也实现不了我们装饰器的功能,走不通装饰器的原则。
#实现三:通过装饰器实现:必须遵循原则:1.不能修改被装饰器源代码 2.不能改被装饰器对象的调用方式
#函数传参的方式有两种,一种是位置形参,一种是通过闭包的方式进行传参
提供面试指导、模拟面试、简历项目优化和职业规划等
负责SRE团队,运维架构(DevOps)、微服务流量治理(K8s、Ingress)、稳定性和可测性系统建设(Prometheus、EFK、Loki)

浙公网安备 33010602011771号