欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Python|闭包&装饰器

程序员文章站 2022-07-12 23:49:03
...

闭包和装饰器

一、闭包

1.定义:

通俗:函数的嵌套

在外部函数中再定义一个内部函数,一般这个内部函数需要外部函数传递过来的参数,我们把这个内部函数和这些参数组成的特殊对象(内存空间)叫做闭包

2.劣势

对于大型的项目来说,闭包可能不够,还是需要类

3.思考:函数、匿名函数、闭包、对象 当做实参时 有什么区别?

  1. 匿名函数能够完成基本的简单功能,,,传递是这个函数的引用 只有功能

  2. 普通函数能够完成较为复杂的功能,,,传递是这个函数的引用 只有功能

  3. 闭包能够将较为复杂的功能,,,传递是这个闭包中的函数以及数据,因此传递是功能+数据

  4. 对象能够完成最为复杂的功能,,,传递是很多数据+很多功能,因此传递是功能+数据

4.nonlocal--关键字

闭包内部函数调用闭包的外部函数中的局部变量

二、装饰器

1.优势:

1.在不修改函数里面代码的情况下修改或增加函数的功能,甚至调用原来代码函数的函数名都不用修改2.函数嵌套,函数调用结束,其创建空间结束3.解决:定义类的时候,Init方法中保存的值,在对象被干掉的时候才消失。其次,类空间中还包括很多其它的魔法属性和方法,也需要占用空间。所以,闭包更加节省空间,

2.功能

1.引入日志2.函数执行时间统计3.执行函数前预备处理4.执行函数后清理功能5.权限校验等场景6.缓存

3.装饰器装饰开始时间

装饰器是在遇到语法糖@就开始装饰在调用之前已经装饰了

4.装饰器装饰

1.一个装饰器可以装饰多个函数, 每装饰一个就相当于创建了一个闭包

5.通用装饰器

  1. 参数全部是多值参数,包括形参和实参2.return 返回,函数(多值参数)

6.一个装饰器装饰多个函数

1.从下面的语法糖开始往上装2.运行的时候从最外层的语法糖往内执行,主程序最先运行完,但是最开始运行的语法糖即最外层(最上面)的语法糖最后执行完

7.疑问:1. 多个装饰器中的内嵌函数同名,会不会影响结果

不会。因为他们虽然函数名相同,但是他们的空间(作用域)不同,一个是局部变量的指向,一个是全局变量的指向

三、demo

1.闭包

def set_fun(func):
    def call_func(*args, **kwargs):  # 这里的参数是报这个闭包搞成通用的
        print("---这是要装饰的1---")
        print("---这是要装饰的2---")
        func(*args, **kwargs)  # 拆包
    return call_func  # 注意这里返回的是内嵌函数的引用,而不是调用内嵌函数;同时注意return的缩进是和谁对齐


# 原主函数
def test():
    print("---我是原来的函数,你不能动我的内部代码---")

a = set_fun(test)
a()  # 调用a

======> 搞成装饰器--修改调用方式:

test=set_fun(test)
test()

2.装饰器

def set_fun(func):
    def call_func(*args, **kwargs):  # 这里的参数是报这个闭包搞成通用的
        print("---这是要装饰的1---")
        print("---这是要装饰的2---")
        return func(*args, **kwargs)  # 拆包
    return call_func  # 注意这里返回的是内嵌函数的引用,而不是调用内嵌函数;同时注意return的缩进是和谁对齐

@set_fun
def test():
    print("---我是原来的函数,你不能动我的内部代码---")
    return "返回想返回的值"
    
# 调用装饰器
test()   --->可以选择传入参数或不传
# 类作为装饰器

class Test(object):
	def __init__(self, func):
		self.func = func

	def __call__(self):
		print("这里是装饰器添加的功能.....")
		return self.func()


@Test  # 相当于get_str = Test(get_str)
def get_str():
	return "haha"

print(get_str())