闭包函数、装饰器

一、闭包函数

  闭包是指在一个函数中定义了另外一个函数,内函数运用了外函数作用域的名字,并且外函数的返回值是内函数的引用,这样就构成了一个闭包函数。

def callFunc():
    n = 1
    def show():
        print('show: ', n)
    return show

s = callFunc()
s()

  去掉了全局变量的使用,将show函数封装在callFunc函数的内部,使外部不可见,不能使用show函数,隐藏了实现细节。

  程序在执行的时候,callFunc返回了内部定义的show函数,并且在show函数内部使用了外部函数的变量。

  在show函数返回时,保存了当前的执行环境,也就是会在show函数中使用外部变量n。

  n只是callFunc函数中的局部变量,当这个函数执行结束时,n自然而然就会被释放。

  但是因为callFunc函数中返回了一个show函数,show函数还在外部执行,所以程序还会将show函数所需的执行环境保存下来

二、装饰器

  装饰器是个什么东东呢?看字面意思好像是装饰什么东东的工具,其实你猜出大概意思了,装饰器本身就是一个函数,这个函数以闭包的形式定义使用 @装饰器函数名 形式来装饰,在不改源代码的情况下,让一个程序增加功能来进行装饰。

  比如在一个项目中,有很多函数,由于项目越来越大,功能越来越多,导致程序越来越慢,其中一个功能函数功能,实现一百万次累加。

def  my_count()
    s = 0
    for i in range(1000001):
        s += i
    print('sum:',s)

  现在要确定函数的运行时间,这个要怎么搞???如何能应用到所有函数上?

  解决方法:

import time

def count_time(func):
    def wrapper():      #wrapper 装饰
        start = time.time()
        func()
        end = time.time()
        print('共计执行:%s 秒'%(end - start)) # 使用%d显示,取整后是0秒,因为不到一秒
    return wrapper

@count_time     # 这实际就相当于解决方法3中的 my_count = count_tiem(my_count)
def my_count():
    s = 0
    for i in range(10000001):
        s += i
    print('sum : ', s)

my_count()

  这样实现的好处是定义好了闭包函数后,只需要通过@xxx的装饰器语法,将@xxx加到要装饰的函数前

  多层装饰器:

import time
 
 
user_dic = {'is_login':None}
 
 
def outter(func):
    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
 
 
def login_auth2(data_source,x,t):
    def login_auth(func):
        def inner(*args, **kwargs):
            if user_dic['is_login']:
                res = func(*args, **kwargs)
                return res
            else:
                if data_source == 'file':
                    username = input('please input your username:')
                    password = input('please input your password:')
                    if username == 'jason' and password == '123':
                        user_dic['is_login'] = True
                        res = func(*args, **kwargs)
                        return res
                    else:
                        print('username or password error')
                elif data_source == 'MySQL':
                    print('from MySQL')
                elif data_source == 'ldap':
                    print('ldap')
                else:
                    print('暂无该数据来源')
        return inner
    return login_auth
 
 
@login_auth2('file',1,2)
# 这一步相当于
# res = login_auth2('file',1,2)  # 这里的res就是login_auth2()的返回值login_auth
# @res
@outter
def index():
    time.sleep(1)
    print('index')
    return 'index'
 
 
index()
# 装饰器在装饰的时候,顺序从下往上
# 装饰器在执行的时候,顺序从上往下
# 这里就实现了给index函数增加了两个功能:计时和认证
# 这里的认证函数是三层嵌套的,最外层函数的作用就是给里层函数传参

  装饰器模板:

  无参装饰器

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)

  有参装饰器

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

  

生前无需久睡,死后自会长眠,努力解决生活中遇到的各种问题,不畏将来,勇敢面对,加油,你是最胖的,哈哈哈
原文地址:https://www.cnblogs.com/panshao51km-cn/p/11182781.html