闭包函数及装饰器

一、闭包函数

定义:定义在函数内部的函数引用了外部函数作用域的名字

第一种
def outter():
    x = 1
    def index():
        print(x)
    return index
res = outter()
print(res)
res()  # 1    利用函数的返回值将函数的值打印出来


  # 首先执行定义函数outter然后执行调用函数outter,接下来执行x=1,接着执行闭包函数index,然后return返回index这个函数,就相当于一个变量名,
  #返回到outter这个调用函数,打印出的结果是index这个函数的id地址  # <function outter.<locals>.index at 0x000001F485AD0AE8>

第二种
def outter():
    x = 1
    def index():
        print(x)
    return index
res = outter()

def func():   # 如果下面在加一个函数,它的值还是为1,因为函数在定义阶已经固定,与调用位置无关
    x = 333
    res()
func()
View Code

如图,此图为闭包函数的操作顺序

给函数体传值得两种方式

第一种:传参

 def index(username):
     print(username)  # 直接通过参数传给函数

第二种:利用必包的形式

def outter(x,y):
    def my_max():
        if x > y:
            return x
        return y
    return my_max
res1 = outter(1,40)   # res1就是my_max函数的地址
print(res1())  # 打印结果为40
res2 = outter(20,30)
print(res2())  # 打印结果为30

# 利用闭包函数,首先在定义函数my_max里输入两个形参,
# 然后调用函数outter里的实参值可以传入定义函数的形参中,在闭包函数中进行比较

二、装饰器

定义:装饰器就是给被装饰对象增加新功能的的一个工具

开放封闭原则:通俗来讲,就是在修改一个项目的需求时,需要给它添加某个或某些功能,但是它的源代码不能更改

装饰器必须遵循的两个原则

1.不改变被装饰多想的源代码

2.不改变被装饰对象(可调用对象)的调用方式

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

1.import time模块
print(time.time())
 1562812014.731474   # 时间戳    当前时间距离1970-1-1 00:00:00相差的秒数
 1970-1-1 00:00:00是Unix诞生元年

time.sleep(1)  # 表示让cpu停止(休息)1秒

装饰器的简单版
import  time
def inner():
    time.sleep(2)
    print('您好!')
inner()  # 会在两秒之后打印“您好!”

#cpu运行的速度非常快,所以代码与代码之间运行的速度非常的快,如果中间需要读取一个文件
# 那么可能会还没读完这个文件,就会运行下面的代码,
#所以可以让cupc中途休息两秒,就可以读取完文件


start = time.time()
inner()
end = time.time()
print('inner run time:%s'%(end-start))   # inner run time:2.000295400619507 # inner的执行时间
View Code

 

2.装饰器的模板

无参函数
from functools import warps
def outter(func):
  @warps(func)
    def inner(*args,**kwargs):  # 在形参中使用
        '执行被装饰函数之前你可以做得操作'
        res = func(*args,**kwargs)  # 在实参中使用
        '执行被装饰函数之后你可以做得操作'
        return res
    return inner


有参函数
from functools import warps
def warppers[date]:
    date = 'file'
    def outter[func]:
    @warps(func)
        def inner[*args,**kwargs]:
            if date == 'file':
                res = func(*args,**kwargs)
                return res
            return inner()
    return outter
View Code

3.装饰器语法糖

注意:

语法糖在书写的时候应该与被装饰对象紧紧挨着,两者之间不能有空格

紧挨着下面可调用对象的名字自动当做它的参数传入

def outter(func):  # func = 最原始的index函数的内存地址
    def get_time(*args, **kwargs):
        start = time.time()
        res = func(*args, **kwargs) 
        end = time.time()
        print('func run time:%s'%(end-start))
        return res
    return get_time


@outter  # index = outter(index)  outter(最原始的index的函数的内存地址)
def index():
    time.sleep(3)
    print('您好!')
    return 'index
View Code

4.认证装饰器

执行函数index之前,必须输入用户名和密码,正确之后才能执行index

否则提示用户输入错误,结束程序

def auth(func):
    # func=index
    def wrapper(*args,**kwargs):
        if current_user['username']:
            print('已经登陆过了')
            res=func(*args,**kwargs)
            return res

        uname=input('用户名>>: ').strip()
        pwd=input('密码>>: ').strip()
        if uname == 'egon' and pwd == '123':
            print('登陆成功')
            current_user['username']=uname
            res=func(*args,**kwargs)
            return res
        else:
            print('用户名或密码错误')
    return wrapper

@auth #index=auth(index)
def index():
    time.sleep(1)
    print('welcome to index page')
    return 122

@auth
def home(name):
    time.sleep(2)
    print('welcome %s to home page' %name)

index()
home('egon')
View Code

5.装饰器修复技术

用户查看被装饰函数的函数名的时候查看到的就是被装饰函数本身
用户查看被装饰函数的注释的时候查看到的就是被装饰函数的注释

from functools import wraps
def outter(func):
    @wraps(func)  # 装饰器修复技术
    def inner(*args,**kwargs):
        """
        inner函数
        :param args:
        :param kwargs:
        :return:
        """
        print('执行被装饰函数之前 你可以执行的操作')
        res = func(*args,**kwargs)
        print('执行被装饰函数之后 你可以执行的操作')
        return res
    return inner
View Code

 5.装饰器应用场景

1.引用日志

2.函数执行时间统计

3.执行函数前预备处理

4.执行函数后清理功能

5.权限校验

6.缓存

原文地址:https://www.cnblogs.com/xiongying4/p/11173520.html