Python闭包与装饰器核心机制及实战详解
本文深入解析Python中闭包与装饰器的核心原理。通过对比匿名函数、普通函数与对象,阐明闭包“功能+数据”的传递特性。详细讲解装饰器的“开放封闭”原则,涵盖无参、有参、不定长参数及返回值处理的通用装饰器实现。重点剖析多层装饰器的执行顺序与类装饰器的用法,帮助开发者掌握Python高级函数编程技巧。
Python闭包与对象的功能对比
闭包的核心内容涉及函数与数据的结合。
匿名函数:适用于执行简单逻辑,其本质是传递函数的引用,仅包含功能逻辑。
普通函数:用于处理复杂业务逻辑,同样通过传递函数引用来实现功能调用。
闭包:能够处理相对复杂的功能场景,其传递的不仅是函数本身,还包含函数运行所需的外部数据,即实现了“功能+数据”的整体传递。
对象:适用于处理最复杂的功能场景,通过传递大量数据与多种功能方法,实现“数据+功能”的综合封装。
———————————————————
关于全局变量的修改:在普通函数内部需使用 global 关键字声明;而在闭包中,若需修改外层函数的变量,则需使用 nonlocal 关键字。
闭包的定义:指两个函数嵌套使用,内部函数可以访问并使用外部函数传递的参数或变量。最终返回的是内部函数的结构及其绑定的数据(基于个人理解)。
基于闭包机制,Python中可以引申出装饰器的概念。
def closure():
# 在函数内部再定义一个函数,
# 并且这个函数用到了外边函数的变量,那么将这个函数以及用到的一些变量称之为闭包
def closure_in(x):
print('---------我是打不死的%s--------' %x)
return closure_in
x = closure()
x('小强')
print('*'*20)
# -----加餐---------
def closure_1(a,b,c):
def closure_on(x):
print('-----%s加餐-------' %b)
print(a*x + c)
return closure_on
demo = closure_1(2,'小强',3) #传closure_1函数
demo(4) #传clsure_on函数
#注:函数不加括号,调用的是函数本身【function】;函数加括号,调用的是函数的return结果。
装饰器基础与开放封闭原则
接下来介绍装饰器的相关内容。
代码设计应遵循“开放封闭”原则:对已存在的代码实现封闭(不随意修改源码),对功能的扩展保持开放(通过装饰器等方式添加新逻辑)。
# 装饰器的作用:为了对原来的代码上进行扩展
def decoration(func):
def call_func():
print('-------正在装饰 -------' )
func()
return call_func
#@decoration #--->demo_new = decoration(demo)
def demo():
print('demo----')
demo_new = decoration(demo)
demo_new()
装饰器实战:从无参到通用装饰器
使用装饰器来测试函数的运行时间:
import time
def set_func(func):
def call_func():
start_time = time.time()
func()
stop_func = time.time()
print(‘alltimes is %f' %(stop_func-start_fun))
return call_func
@set_func
def test1():
print(‘——-test1———')
test1()
#等价于:
@set_func==test1 = set_func(test1)
1. 针对没有参数且没有返回值的函数进行装饰:
def set_func(func):
def call_func():
print(‘———test2——-')
print(‘———-test3——')
func()
return call_func
@set_func
def test1():
print(‘——test1——- ')
2. 针对有参数但无返回值的函数进行装饰:
def set_func(func):
def call_func(a): #变
print(‘———test2——-')
print(‘———-test3——')
func(a) #变
return call_func
@set_func
def test1(num):
print(‘——test1——- %d ' %num)
test1(100) —->call_func(100)
test1(200)——>call_func(200)
以下是装饰器原理的复现过程:
————————————————————————-
关键点:只要代码中出现 @函数名 这一行(即装饰器语法),在程序加载阶段就会立即执行该装饰器逻辑。
3. 针对不定长参数的函数进行装饰:
def set_func(func):
def call_func(*args,**kwargs): #变
print(‘———test2——-')
print(‘———-test3——')
func(*args,**kwargs) #(拆包)将元祖拆开,每个进行传输;
#func(args,kwargs)—>不行,相当于传递了两个参数:一个元祖,一个字典。
return call_func
@set_func
def test1(num,*args,**kwargs):
print(‘——test1——- %d ' %num)
print(‘——test1——- ' , args)
print(‘——test1——- ' ,kwargs )
test1(100)
test1(100,200)
test1(100,200,300,mm=100)
注意:*args 用于保存不定长位置参数,以元组形式存储;**kwargs 用于保存不定长关键字参数,以字典形式存储(如 mm=...)。
4. 针对带有返回值的参数进行装饰,以及通用装饰器的实现:
#通用装饰器
def set_func(func):
print(“开始进行装饰———-”)
def call_func(*args,**kwargs): #变
print(‘———test2——-')
print(‘———-test3——')
return func(*args,**kwargs) #(拆包)将元祖拆开,每个进行传输;如果没有return ret返回none。
#func(args,kwargs)—>不行,相当于传递了两个参数:一个元祖,一个字典。
return call_func
@set_func
def test1(num,*args,**kwargs):
print(‘——test1——- %d ' %num)
print(‘——test1——- ' , args)
print(‘——test1——- ' ,kwargs )
return ‘ok' #—-返回给上面的func(),然后return func—ret
ret = test1(100)
5. 多个装饰器同时作用于同一个函数的情况:
def add_qx(func):
print(“——开始进行装饰权限1———-”)
def call_func(*args,**kwargs): #变
print(‘这是权限验证1')
return func(*args,**kwargs)
return call_func
def add_xx(func):
print(“——开始进行装饰xx功能———-”)
def call_func(*args,**kwargs): #变
print(‘这是xx权限验证')
return func(*args,**kwargs)
return call_func
@add_qx
@add_xx
def test1():
print(‘——test1——-')
test1()
多层装饰器执行顺序与类装饰器
执行逻辑:首先执行第一个装饰器,但此时其下方的直接目标不是原始函数(根据装饰器原则,装饰器下方必须最终指向函数,否则不执行),因此第一个装饰器先挂起等待。待第二个装饰器执行完毕形成新的函数后,再将该函数交给第一个装饰器处理。因此,最终的运行结果顺序如下:
开始执行装饰xx的功能,
开始执行装饰权限1,
这是权限验证1,
这是xx权限验证,
——-test1——-,
——————装饰器练习—————- 预期输出格式:<td><h1>haha</h1></td>
def set_func_1(func):
def call_func():
return ‘<h1>' + func() + '</h1>'
return call_func
def set_func_2(func):
def call_func():
return ‘<td>' + func() + '</td>'
return call_func
@set_func_1()
@set_func_2()
def get_str():
return ‘haha'
print(get_str())
最后执行的效果: <h1><td>haha</td></h1>
6. 使用类对函数进行装饰(了解):
class Test(object):
def __init__(self,func):
self.func = fun
def __call__(self):
print(‘这里是装饰器的功能。。。。')
return self.func()
@Test
def get_str():
return ‘haha'
print(get_str())
以上就是装饰器与闭包的全部内容。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













