Day59 Python--闭包&装饰器

一,函数知识点回顾

def func():
    pass

print(func)  #函数名对应内存地址

a = func  #可以赋值给变量
a()
 
def func2(arg):  #可以做参数
    arg()
func2(func)

def func3():  #可以做返回值
    def fun4():
        pass
    return func4

lis = [func,func2,func3,func4]  #可以做容器对象的元素
for i in lis:
    i()

二,闭包

  定义:如果一个内层函数包含了对外层函数变量的引用,那这个内层函数就是闭包

def wrapper(name):
    def inner():
        print(name) #相当内层函数的空间里保留了name变量的引用并且指向当初传入的实参
    return inner
ret = wrapper('123')  #当函数执行时,Python解释器会开辟一块内存(局部名称空间)来储存这个函数里面的内容,这个时候,Python解释器才关注函数里面变量名和值之间对应的关系,包括内层函数内的内容

del wrapper
ret()     # 指向inner的内存地址
wrapper('123')  #报错:NameError: name 'wrapper' is not defined
闭包如何保存局部变量的数据
#灵魂三问1
def func1():
    num = 100
    def func2(arg):
        print(arg)
    func2(num)  #通过传参的方式,向内层函数传递数据

func1()  

#灵魂三问2
def func1():
    num = 100
    def func2()
        print(num)  #内层函数的作用域里没有num,会自动往外层函数的作用域去找
    func2()

func1()

#灵魂三问3
def func1(num):
    def func2():
        print(num)  #内层函数的作用域路没有num,会自动往外层函数的作用域去找
    func2()

func1()
看起来好像很牛b的闭包灵魂三问
#内层函数+其外层函数变量的引用
def func1(name):
    def func2():
        print(name)
    return func2

ret = func1('alex')
ret()

#非闭包
def func1():
    def func2():
        def func3():
            def func4():
                pass
            return func4
        return func3
    return func2

ret1 = func1()  #func2
ret2 = ret1() #func3
ret3 = ret2() #func4
ret3()
闭包的变形

三,装饰器初识 

#装饰器的定义:
既不想直接修改原来的函数,也不想修改函数的调用方式,还要加新功能的时候,可以使用装饰器
def wrapper(func): def inner(*args,**kwargs): print('新功能') func(*args,**kwargs) return inner
#global_func = wrapper(global_func) 内层的inner函数,引用了func,func -指向-> global_func
@wrapper  #相当于把被装饰的函数当成参数传给a,然后把返回值再赋值给被装饰的函数名
def global_func(): pass

global_func() #相当于调用了内层函数inner

四,装饰器进阶

  1.装饰带参数的函数

# 装饰带参数的函数


def wrapper(func):
    def inner(*args, **kwargs):  # 实际执行函数的参数
        print('开始')
        r = func(*args, **kwargs)
        print(r)
        print('结束')
        return r
    return inner


@wrapper
def my_sum(x, y):
    print('我是my_sum函数')
    return x + y


ret = my_sum(10, 20)  # inner(10, 20)
print(ret)

  2.装饰带返回值的函数

# 装饰带返回值的函数
def wrapper(func):
    def inner():
        print('开始')
        r = func()  # 拿到原来函数的返回值
        print('结束')
        return r
    return inner


@wrapper
def f1():
    print('我是f1')
    return 100


ret = f1() #实际上是执行了inner内层函数,如果inner内层没用renturn返回值,则f1也没用返回值

  3.带参数的装饰器  *****

def mougehanshu(arg):
    def wrapper(func):
        def inner(*args, **kwargs):
            print('欢迎VIP用户进入{}专栏!'.format(arg))
            func(*args, **kwargs)
        return inner
    return wrapper

# wrapper = mougehanshu()
#@mougehans(参数) 相当于 @wrapper


@mougehanshu('电影')  # 相当于mougehanshu()执行后返回wrapper
def movie():
    print('这是电影专栏!')


@mougehanshu('体育')  # @wrapper
def sport():
    print('这是体育专栏!')

  4.多个装饰器装饰同一个函数  *****

def foo1(func):
    print("d1")

    def inner1():
        print("inner1")
        return "<i>{}</i>".format(func())

    return inner1


def foo2(func):
    print("d2")

    def inner2():
        print("inner2")
        return "<b>{}</b>".format(func())

    return inner2


@foo1   #f1 = foo1(foo2(f1))=foo1(inner2,打印d2) = inner1 打印'd1'
@foo2   #执行foo2(f1) =inner2 打印'd2'
def f1():
    return "我是f1"

ret = f1()
print(ret)

# f1 = foo2(f1)    --> inner2
# f1 = foo1(inner2)  --> inner1
↓↓
#执行流程分析:
#f1()  ==  inner1()->打印'inner1'->return "<i>{}</i>".format(inner2())
#inner2() -> 打印'inner2'->return "<b>{}</b>".format(f1())
#f1() -> return "我是f1"
↓↓
print(ret) ---> '<i><b>我是f1</b></i>'

  5.装饰器修复技术  ****

# 装饰器修复技术
from functools import wraps

# Flask框架的时候用得上


def wrapper(func):
    @wraps(func)
    def inner(*args, **kwargs):
        print('这是新功能')
        func(*args, **kwargs)
    return inner


@wrapper
def f1(arg1, arg2):
    """
    这里写这个函数是做什么的
    :param arg1: 这个参数是什么类型的
    :param arg2: 这个参数是什么类型
    :return: None
    """
    print('嘿嘿嘿')


print(f1.__doc__)  
print(f1.__name__)
#若不修复的话,f1实际是指向inner的内存空间,
#f1.__doc__ 相当于 inner.__doc__中的内容
#f1.__name__ 相当于 inner.__name__中的内容

五,装饰器究极进阶

  1.类装饰器

  2.装饰类

猜你喜欢

转载自www.cnblogs.com/lianyeah/p/9884701.html