闭包函数及装饰器

一.闭包函数

闭包函数:

1.闭:定义在函数内部的函数
2.包:内部函数引用了外部函数作用域的名字

可以用闭包来给函数传参

def outter(x):
    def inner():
        print(x)
        return 100

    return inner


res = outter(1233)

print(res())
View Code

二.装饰器

装饰器就是闭包函数的一种应用场景

1.为什么要用装饰器

开放封闭原则:
      开放:对扩展开放
      封闭:对修改封闭

2.装饰器简介

装饰器(可调用对象)需要遵守的两个原则:
1.不改变被调用装饰对象的源码
2.不改变被调用装饰对象调用方式

装饰器的目标:为可调用对象增加新的功能。(就像是给一个丑陋的盒子,用一层精美的包装自装扮起来)

2.装饰器模板

 装饰器的通用写法

无参

from functools import wraps

def outter(func):
    @wraps(func)
    def built_inner(*args, **kwargs):
        print("函数执行之前的操作")

        res = func(*args, **kwargs)
        print("函数执行之后的操作")
        return res

    return built_inner

@outter
def index():
    print("index")


index()
print(help(index))  # 查看函数的注释
print(index.__name__)
View Code

有参

from functools import wraps


def wrapper(source):
    def outter(func):

        @wraps(func)
        def built_inner(*args, **kwargs):
            print("函数执行之前的操作")

            res = func(*args, **kwargs)
            print("函数执行之后的操作")
            return res

        return built_inner

    return outter


@wrapper(1)
def index():
    print("index")
    

index()
print(help(index))  # 查看函数的注释
print(index.__name__)
View Code

3.语法糖

@outter  # @outter 等价于 for_rang = outter(for_rang) 
def for_rang():
    time.sleep(1)
    for i in range(1, 10):
        for j in range(1, i + 1):
            print("%s*%s=%2s " % (i, j, i * j), end="")
        print()
View Code

语法糖在书写的时候应该与被调用的对象紧紧挨着 ,两者之间不要有空行。

4.多层装饰器 

装饰器在装饰顺序    从下往上
装饰器执行时顺序    从上往下

def outter1(func1):
    print('加载了outter1')
    def wrapper1(*args,**kwargs):
        print('执行了wrapper1')
        res1=func1(*args,**kwargs)
        return res1
    return wrapper1
def outter2(func2):
    print('加载了outter2')
    def wrapper2(*args,**kwargs):
        print('执行了wrapper2')
        res2=func2(*args,**kwargs)
        return res2
    return wrapper2
def outter3(func3):
    print('加载了outter3')
    def wrapper3(*args,**kwargs):
        print('执行了wrapper3')
        res3=func3(*args,**kwargs)
        return res3
    return wrapper3
@outter1  # index = outter1(wapper2)
@outter2  # wrapper2 = outter2(wrapper3)
@outter3  # wrapper3 = outter3(最原始的index函数内存地址)
def index():
    print('from index')

index()
View Code

5.装饰器的伪装

用户查看被装饰函数的函数名和注释时看到的就是被装饰函数和它的注释

from functools import wraps

def outter(func):
    @ wraps(func)
    def get_time(*args, **kwargs):
        """
        this is get_time
        :param args: 
        :param kwargs: 
        :return: 
        """
        start = time.time()
        res = func(*args, **kwargs)
        end = time.time()
        print(end - start)
        return res
    return get_time
def wrapper1(func):
    @wraps(func)
    def confirm_(*args, **kwargs):
        """
        this is confirm
        :param args: 
        :param kwargs: 
        :return: 
        """
        username = input("username>>:").strip()
        psw = input("password>>:").strip()
        if username == "jason" and psw == "123":
            res = func(*args, **kwargs)
            return res
        else:
            print("输出错误")
    return confirm_
View Code
原文地址:https://www.cnblogs.com/Cpsyche/p/11171134.html