【python 第五日】 函数闭包与装饰器

函数闭包:

  概念:函数内部嵌套函数,并且外部函数返回内部函数,嵌套函数用到外部函数的局部变量,嵌套函数+局部变量=闭包

def a1():
    a=1
    def a2():
        nonlocal  a   #如果不加这一句,下一句会报错,说a未定义,但是如果下一句用b=a+1 这时候可以不用添加
        a = a + 1
        print(f"a2的a都是{a}")
    print(f"a1的a都是{a}")
    return a2

x=a1()()

输出如下:
a1的a都是1
a2的a都是2

a2() 和a变量一起组成了闭包

装饰器

装饰器:本质就是函数,返回内部函数,内部函数有调用函数的接口,功能是为其他函数添加附加功能=高级函数+闭包+函数嵌套

原则:

1、不修改原函数的调用方式

2、不修改原函数的源代码

 返回值问题:最后返回的是嵌套函数的返回值,不是原函数的返回值

@timer 装饰器问题,即使没有test(),他也会运行

#运行test() 相当于运行wrapper(),所以是wrapper的返回值
import time
def timer(func):
def wrapper(*args, **kwargs):
start_time= time.time()
print("wrapper开始了。")
# f_res = func(*args, **kwargs) # 如果运行注释的函数,这样可以返回原函数的返回值
func(*args, **kwargs)
end_time= time.time()
print("wrapper结束: 共用时间:%d秒" %(end_time - start_time))
return "这是wrapper的返回值"
# return f_res
return wrapper

@timer #相当于test = timer(test) ####这一步编译的时候就运行了 即使没有test() 这一个也会运行
def test(*args, **kwargs):
print("test 开始运行")
time.sleep(3)
return '这是test的返回值'

res = test()
print(res)
#输出如下: wrapper开始了。 test 开始运行 wrapper结束: 共用时间:3秒 这是wrapper的返回值

 解包

a,*d,c=[1,2,3,4,5,6]
a是1 c是6,中间的全部弄到d中了 ,但是*后面必须跟个变量名
a,b=b,a 交换a,b的值

可选择的修饰器

就在原来修饰器外面添加个选择函数

import time

def  consumption(func):
    print("消费开始:")
    def inner(*args, **kwargs):
        print("内部消费开始:")
        res = func(*args, **kwargs)
        print("内部消费结束")
        return res
    return  inner

@consumption  
def chifan():
    time.sleep(3)
    print("我吃完饭了,用来3秒")

@consumption 
def read_book():
    time.sleep(0.5)
    print("我读完书了,用了0.5")

chifan()


#输出如下: 两个消费开始说明,先运行了两次@consumption
消费开始:
消费开始:
内部消费开始:
我吃完饭了,用来3秒
内部消费结束


import time
def cons(select=1): #在原来外面添加一个选择函数
def consumption(func):
print("消费开始:")
def inner(*args, **kwargs):
if select == 1:
print("内部消费1开始:")
res = func(*args, **kwargs)
print("内部消费1结束")
return res
elif select == 2:
print("内部消费2开始:")
res = func(*args, **kwargs)
print("内部消费2结束")
return res
return inner
return consumption

@cons(2) #这里可以选择消费类型
def chifan():
time.sleep(3)
print("我吃完饭了,用来3秒")

@cons(1) #这里可以选择消费类型
def read_book():
time.sleep(0.5)
print("我读完书了,用了0.5")

chifan()

read_book()


#输出如下:

消费开始:
消费开始:
内部消费2开始:
我吃完饭了,用来3秒
内部消费2结束
内部消费1开始:
我读完书了,用了0.5
内部消费1结束

 

多重修饰器



def dec1(func):
print("HHHA:0====>")
def one():
print("HHHA:0.1====>")
func()
print("HHHA:0.2====>")
return one


def dec2(func):
print("HHHB:0====>")
def two():
print("HHHB:0.1====>")
func()
print("HHHB:0.2====>")
return two


def dec3(func):
print("HHHC:0====>")
def three():
print("HHHC:0.1====>")
func()
print("HHHC:0.2====>")
return three

@dec1
@dec2
@dec3
def test():
print("HHHD:0====>test")


test()

输出如下:

HHHC:0====>
HHHB:0====>
HHHA:0====>
HHHA:0.1====>
HHHB:0.1====>
HHHC:0.1====>
HHHD:0====>test
HHHC:0.2====>
HHHB:0.2====>
HHHA:0.2====>

组装阶段从下到上   test->dec3->dec2->dec1   执行阶段:one->two->three  调用关系从上到下

函数前阶段,从上到下    

函数

函数后阶段:从下到上

def log(text):
    print("HHHA:0====>")
    def decorator(func):
        print("HHHA:0.1====>")
        def wrapper(*args, **kw):
            print("HHHA:0.1.1====>")
            return func(*args, **kw)
        print("HHHA:0.2====>")
        return wrapper
    print("HHHA:1====>")
    return decorator

@log('execute')
def now():
    print('HHHB:=====>test')

now()

#输出如下:
HHHA:0====>
HHHA:1====>
HHHA:0.1====>
HHHA:0.2====>
HHHA:0.1.1====>
HHHB:=====>test
先执行含餐部分
再执行装饰器部分
再调用部分

支付宝     
您的资助是我最大的动力!
金额随意,欢迎来赏!
微信

如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的关注我

如果,想给予我更多的鼓励,求打       付款后有任何问题请给我留言!!!

------------------------------------------------------------------------------------------
作者:【周sir】
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
原文地址:https://www.cnblogs.com/zhouguanglu/p/10178438.html