闭包函数及装饰器

一、什么是闭包函数

1.1完整定义:

定义在函数内部的函数,并且该函数包含对外部函数作用域的引用

闭包函数提供了另一种为函数体传值的方式:外层函数包一个值给他

def outter():
    x=1 # 外部传一个值给内部函数
    def inner():
        print(x)# 需要一个值
    return inner # return打破层级的限制

二、装饰器

2.1为什么要有装饰器?

软件一旦上线,就应该遵守开放封闭原则:对功能升级开放,不允许修改源代码以及调用方式

2.2装饰器的简单版本

import time
def my_time(): # 原本函数
    time.sleep(0.5)
    print('统计时间')
def warpper(func):# 定义装饰器
    def inner():
        start_time=time.time()
        my_time()
        stop_time=time.time()
        print(stop_time-start_time)
    return inner
res=warpper(my_time)
res()

2.3装饰器的升级版

一、加入返回值,并支持调多个函数

import time
def my_time():
    time.sleep(0.5)
    print('统计时间')
    return 123 # my_time函数有返回值
def warpper(func):
    def inner():
        start_time=time.time()
        res2=func()# 被调用的函数inner内部加返回值;并且用func来代替具体函数名,从而调用更多不同函数
        stop_time=time.time()
        print(stop_time-start_time)
        return res2 #被调用函数inner内部加return
    return inner
my_time=warpper(my_time)
res=my_time()
print(res)
my_time函数有返回值,而my_time()调用的是inner内部的函数,而他无返回值,所以要加

二、当出现有参函数时

import time
def my_time(name): # 出现有参函数
    time.sleep(0.5)
    print('统计时间')
    return 123
def warpper(func):
    def inner(*args,**kwargs): #  被调用的函数加入可变参数
        start_time=time.time()
        res2=func(*args,**kwargs) # 加入可变参数
        stop_time=time.time()
        print(stop_time-start_time)
        return res2
    return inner
my_time=warpper(my_time)
res=my_time('wuxi') #此处必须指定参数
print(res)

三、装饰器的基本形式产生

def warpper(func):
    def inner(*args,**kwargs):
        print('此处填写要加入的功能')
        res2=func(*args,**kwargs)
        print('此处填写要加入的功能')
        return res2
    return inner

 正常我们情况下查看函数的一些信息的方法(原来的函数的函数名;原来的函数的注释)在此处都会失效。都会返回装饰函数的函数名和注释,如何使用户查看不出该函数被装饰过呢?

采用from functools import wraps

@warps方法

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

    @outter
    def index(username,*args,**kwargs):
        """index注释"""
        pass
    print(index)

    装饰器修复技术

        1.返回原来的函数的函数名
        2.返回原来的函数的注释

三、装饰器语法糖

@+装饰器名。写在"装饰器"下和需要调用的函数上面。

方便人直接调用函数

def warpper(func):
    def inner(*args,**kwargs):
        res2=func(*args,**kwargs)
        return res2
    return inner
@warpper #index=warpper(index) # index=inner
def index():
    print('...')
index()
#@warpper 把正下方的紧挨着的函数名当做参数传入装饰器,并赋值给该函数

现在只需直接调用index。如果index函数有返回值的话,要赋值一下再print

多个语法糖叠加

装饰时:从下往上
执行时:从上往下
@outter1#index=outter(func2)
@outter2#func2=outter2(func1)
@outter3#func1=outter3(index)

有参装饰器(装饰器最复杂的版本)

def wrappers(data):
    # data = 'file'
    def outter(func):
        def inner(*args,**kwargs):
            if data == 'file':
                # 执行被装饰函数之前你可以做的操作
                res = func(*args,**kwargs)  # * **在实参中使用
                # 执行被装饰函数之后你可以做到操作
                return res
        return inner
    return outter

3.1现在来写一个认证装饰器

import time
d={
    'username':None,
}
def outter(func):
    def inner(*args,**kwargs):
        if d['username']:
            res = func(*args, **kwargs)
            return res
        else:
            username=input('用户名:>>>').strip()
            password=input('密码:>>>').strip()
            if username =='wuxi' and password== '123':
                print('登录成功')
                d['username']=True
                res=func(*args,**kwargs)
                return res
            else:
                print('用户名或密码错误')
    return  inner
@outter# inner=outter(index)
#index=inner
def index():
    time.sleep(0.1)
    return 1111111111111
@outter# inner=outter(home)
#home=inner
def home(name):
    time.sleep(1)
    print('welcome to %s page'%name)
res2=index()
print(res2)
home('wx')

 

posted @ 2019-07-11 17:11  xg1321  阅读(147)  评论(0编辑  收藏  举报