闭包函数与装饰器

今日内容


 

闭包函数:


 

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

    x = 1

    def inner()

        print(x)   # 这一步引用 x = 1

    return inner

res = outter()

res()  # 1 

def func()

    x = 2

   res()  # 这里相当于 res(outter()),而res()的调用结果为1

func()  #  1 ,这里调用func函数,执行内部函数代码,虽然x = 2存在,但是执行res()后,又执行了一次x = 1赋值,所以结果返回1  
  • 给函数体传值的第一种方式:传参
def index(username):

    print(username)
  • 给函数体传值的第二种方式:闭包
def outter()

    x = 1

    y = 2

    def my_max():

        if x > y:

            return x

        return y

    return my_max

res = outter()  # res 就是my_max函数的内存地址

res()  # my_max函数的内存地址

print(res())  #结果为x,y中的最大值 
闭包方式1

或者

def outter(x,y)

    def my_max():

        if x > y:

            return x

        return y

    return my_max

res = outter(1,2)  # res 就是my_max函数的内存地址

res()  #  my_max函数的内存地址

print(res())  # x,y中的最大值
闭包方式2

Pycharm解释器知识点: pip3 install requests装requests模块

  • 函数传参的第一种方式:直接给函数传参
import requests   # 导入requests模块

def my_get(url):

    response = requests.get(url)

    if response.status_code == 200:

        print(len(response.text))

my_get('此处输入网址')    
直接给函数传参
  • 函数传参的第二种方式:*闭包*
import requests

def outer()

    url = '网址'

    def my_get():

        response = requests.get(url)

        if response.status_code == 200:

            print(len(response.text))

    return my_get()

my_jd = outter('此处输入网址')

my_jd()   # 相当于my_jd(outter())

my_baidu = outter('此处输入网址')

my_baidu()   # 相当于my_baidu(outter())

 

装饰器:


 

装饰器:用工具给被装饰对象添加新的功能

开放封闭原则:

  • 开放:对扩张开放 (你扩展没事,别减少代码)
  • 封闭:对修改封闭 (不被允许修改原代码\被修饰函数代码)

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

  • 1.不改变被装饰对象源代码
  • 2.不改变被装饰对象(可调用对象)的调用方式
def index():

    pass

index()   # 上面定义的index函数,你就老老实实的用常规方式调用index()函数

关于如何使用?

  • 1.统计index函数执行时间
import time

print(time.time(3))  # 1562812014.731474 时间戳,当前时间距离1970-1-1 00:00:00相差的秒数

def index():

    print('XXXXXX')

time.sleep(3)  # 此处是让cpu睡3秒

print('XXXXX')  # 这是返回输出XXXXX所执行的时间
  • 2.下面是常规的用start和end来记录当前时间:
import time

def index():

    time.sleep(3)

    print('XXXXXX')

strat = time.time()

index()

end = time.time()

print('index run time:%s'%(end-start))   # 返回的是index函数从开始到结束的运行时间差
  • 3.下面是初步装饰函数:
import time

def index():

    time.sleep(3)

    print('XXXXXX')

def get_time(func)  # func=index函数

    strat = time.time()

    func()  # func=index函数内存地址()

    end = time.time()

    print('index run time:%s'%(end-start))

get_time(index)

装饰器简单版本:

import time

def index():

    time.sleep(3)

    print('XXXXXX')

def outter(func):

    def get_time():

        start = time.time()

        func()

        end = time.time()

        print('index run time:%s' % (end - start))

    return get_time

res = outter(index)

res()
简单版本

装饰器进化版本:

如果我们要统计login执行时间:

import time

def index():

    time.sleep(3)

    print('XXXXXX')


def login(name):

    time.sleep(1)

    print('%s is sb'%name)


def outter(func):  # func = 最开始的login函数的内存地址

    def get_time(*args,**kwargs):  # args = ('egon',) kwargs = {} 

        strat = time.time()

        func(*args,**kwargs)  # func=最开始的login函数内存地址() 直接调用

        end = time.time()

        print('index run time:%s'%(end-start))

    return get_time

login = outter(login)  # outer(最开始的login函数内存地址) 

login('egon')        
View Code
import time

def index():

    time.sleep(3)

    print('XXXXXX')


def login(name):

    time.sleep(1)

    print('%s is sb'%name)


def outter(func):  # func = 最开始的login函数的内存地址 

    def get_time(*args,**kwargs):  # args = ('egon',) kwargs = {} 

       strat = time.time()

        res = func(*args,**kwargs)  # func=最开始的login函数内存地址() 直接调用

        return res

        end = time.time()

        print('index run time:%s'%(end-start))

    return get_time

login = outter(login)  # outer(最开始的login函数内存地址)

res = login('egon')

login('egon')    
View Code2

''''''

函数参数的问题:无参函数和有参函数是否都可以直接调用

函数可以接收任意数量的参数

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

'''''' 

def outter(func):

    def get_time(*args,**kwargs):

        strat = time.time()

        func(*args,**kwargs)

        return res

        end = time.time()

        print('index run time:%s'%(end-start))

    return get_time

 
@outter  # login = outer(index)

def index():

    time.sleep(3)

    print('XXXXXX')

 
@outter  # login = outer(login)

def login(name):

    time.sleep(1)

    print('%s is sb'%name)
语法糖的应用

装饰器模板:

def outter(func):

    def inner(*args,**kwargs):

        print('执行被装饰函数之前,你可以做的操作')

        res = func(*args,**kwargs)

        print('执行被装饰函数之后,你可以做的操作')

        return res

    return inner

认证装饰器:

执行函数index之前必须先输入用户名和密码,正确之后才能执行index;否则提示用户输入错误,结束程序

import time

    user_dic = {'is_login':None}

    def login_auth(func):  # 其实就是func = index

        def inner(*args,**kwargs):

            if user_dic['is_login']:

                res = func(*args,**kwargs)

                return res

            else:

                username = input('请输入用户名:').strip()

                password = input('请输入密码:').strip()

                if username == 'jason' and password == '123':

                    user_dic['is_login'] = True

                    res = func(*args,**kwargs)

                    return res

                else:

                    print('用户名或者密码错误')

        return inner

 
@login_auth

def index(name):

    time.sleep(1)

    print('%s is dsb'%name)    
认证装饰器

 


 

多层装饰器:(重要)


 

装饰器在装饰的时候,顺序是从下往上

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

import time


def outter(func):

    def get_time(*args,**kwargs):

        strat = time.time()

        res = func(*args,**kwargs)

        return res

        end = time.time()

        print('index run time:%s'%(end-start))

    return get_time


def login_auth(func):  # 其实就是func = index

    def inner(*args,**kwargs):  # 这里的参数是跟被装饰函数的参数一一对应的

        if user_dic['is_login']:

            res = func(*args,**kwargs)

            return res

        else:

            username = input('请输入用户名:').strip()

            password = input('请输入密码:').strip()

            if username == 'jason' and password == '123':

                user_dic['is_login'] = True

                res = func(*args,**kwargs)

                return res

            else:

                print('用户名或者密码错误')

    return inner

 
@login_auth  # index = login_auth(get_time) index = inner函数的内存地址

@outter  # get_time = outter(index) index是最开始的index

def index(name):

    time.sleep(1)

    print('%s is dsb'%name)    
多层装饰器

三层装饰器:(重要)


 

def login_auth2(data_source)

    def login_auth(func):  # 其实就是func = index

        def inner(*args,**kwargs):  # 这里的参数是跟被装饰函数的参数一一对应的

           if user_dic['is_login']:

                res = func(*args,**kwargs)

                return res

            else:

                if data_source == 'file':

                    username = input('请输入用户名:').strip()

                    password = input('请输入密码:').strip()

                    if username == 'jason' and password == '123':

                        user_dic['is_login'] = True

                        res = func(*args,**kwargs)

                        return res

                    else:

                        print('用户名或者密码错误')

                elif data_source == 'MYSQL':

                    print('form MYSQL')

                elif data_source == 'ldsp':

                    print('from ldsp')

                else:

                    print('暂时无数据来源')

        return inner

 
@login_auth2(data_source,x,t)  # login_auth2(data_source,x,t)等价于login_auth,data_source = 'file' 

@outter  # get_time = outter(index) index是最开始的index

def index(name):

    time.sleep(1)

    print('%s is dsb'%name)                
三层装饰器

装饰器补充:

我们用装饰器的最终目标就是:

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

方法就是下面这两句代码:

form functools import wraps

@wraps(func) '''装饰器修复技术'''

form functools import wraps

def outter(func):

    @wraps(func)  # 装饰器修复技术

    def inner(*args,**kwargs):

        print('执行被装饰函数之前,你可以做的操作')

        res = func(*args,**kwargs)

        print('执行被装饰函数之后,你可以做的操作')

        return res

    return inner

 
@outter  # outter(最原始的index内存地址)

def index():
'''
这是index函数
:return
'''
print(index)

print(help(index))  # 查看函数的注释

print(index.name)  # 查看函数名字字符串形式
装饰器补充

 

 

posted @ 2019-07-13 02:40  泡泡茶壶i  阅读(199)  评论(0编辑  收藏  举报