Skip to content

Latest commit

 

History

History
143 lines (110 loc) · 3.96 KB

Python的闭包与装饰器.md

File metadata and controls

143 lines (110 loc) · 3.96 KB

闭包

内部函数对外部函数作用域里变量的引用

闭包内的闭包函数(内部函数)私有化了变量,完成了数据的封装,类似于面向对象

def func():  # 外部函数
    a = 1  # 外部函数作用域里的变量
    print("this is func.")
    def func1(num):  # 内部函数
        print("this is func1")
        print(num + a)
    return func1  # 返回func1函数本身
      
var = func()  # var = func1  
# var()  # 调用func1函数  
var(3)  # 4

函数内的变量(属性),都是有生命周期的,生命周期都是在函数执行期间

# 作用域
def func():
    a = 1
    
func()
print(a)  # 函数内的东西只有在函数运行期间他才会存活

怎么去实现一个闭包函数?

mylist = [1, 2, 3, 4, 5]

def func(obj):
    print('func:', obj)
    def func1():
        obj[0] += 1  # 列表索引可以修改对应位置上的值
        print('func1:', obj)
    return func1  # 让外部函数返回内部函数即可  这就是一个闭包

# 调用func(),传入一个列表mylist,返回函数func1  即var = func1,这样var就成了一个函数
var = func(mylist)  
# 调用var函数
var()  
var()
var()
# var: obj  print('func1:', obj)

作用域

装饰器,语法糖 @

装饰器

装饰器所存在的意义:不影响原有函数的功能,还能添加新的功能

# 在执行func的时候,首先会执行func1中的内容
@func1  # 这算是装饰器函数
def func():
    print('aaa')

一般常见于当拿到了第三方$API$,人家的$API$是不允许修改的。如果觉得这个$API$写的特别简陋,需要添加某些功能,那么就可以使用装饰器

装饰器基于闭包

普通装饰器

def func1(func):  # 函数func1接收的参数是一个函数func  这里的func函数其实就是下面的myprint函数  外部闭包函数的参数是被装饰的函数对象
    def func2():
        print('aaabbb')
        return func()  # 返回了外部函数接收的被装饰函数myprint的调用
    return func2  

# return func  # 返回了函数对象
# return func()  # 返回的是一个函数调用,其实真正意义上返回的是函数执行完成之后的结果
# 1. func1(myprint) --> func2
# 2. func2() --> print('aaabbb')  return func()
@func1  # @func1 <==> func1(myprint)()  # 接收被装饰的函数作为参数,而且还要继续调用一次  有两个函数调用
def myprint():
    print('你好,我是print')

 myprint()  # 执行func1(myprint)()     

装饰器函数带参数:多一层包装来接收装饰器的参数

# 构建一个装饰器
def arg_func(sex):
    def func1(b_func):  # 传的是装饰器装饰的函数man或者woman
        def func2():
            if sex == 'man':
                print('你不可以生娃')
            if sex == 'woman':
                print('你可以生娃')
            return b_func()
        return func2  # 让外部函数返回内部函数即可  这就是一个闭包
    return func1

# arg_func(sex='man') --> func1
# arg_func(sex='man')(man) --> func1(man) --> func2
# arg_func(sex='man')(man)() --> func1(man)() --> func2() -->man()
@arg_func(sex='man')
def man():
    print('好好上班。')
    
@arg_func(sex='woman')    
def woman():
    print('好好上班。')
    
# arg_func(sex='man') --> func1
# arg_func(sex='man')(man) --> func1(man) --> func2
# arg_func(sex='man')(man)() --> func1(man)() --> func2() -->man()
man()  
woman()  

被装饰的函数带参数:只需要在最内部函数传入参数即可

# 先写出来一个装饰器
def func1(func):  # 外部装饰器函数func1接收mysum作为参数传递进来
    def func2(x, y):  # x, y就是func的参数  mysum的参数会被内部真正的这个闭包函数所接收到
        print(x, y)
        x += 5
        y += 5
        return func(x, y)  # 在内部函数调用被装饰的函数
    return func2

@func1
def mysum(a, b):  # a = a + 5  b = b + 5
    print(a + b)