python:闭包,装饰器

闭包:

闭包只能存才嵌套函数中
内层函数对外层还输非全局变量的引用,就会形成闭包
被引用的非全局标量也称作自由变量,这个自由变量会与内层函数产生一个绑定关系
自由变量不会在内存中消失

# __code__.co_freevars : 函数的属性,获取函数中的自由变量

def wrapper():
    l = []    #这个l 是个自由变量,在函数外部是不能改变 l 的值
    def inner(val):
        l.append(val)
        return sum(l)/len(l)
    return inner
ret = wrapper()
print(ret.__code__.co_freevars)    # ('l',),可以当做判断一个函数是不是闭包


def wrapper(a,b):    # 这里a,b也是自由变量
    def inner():
        res = a+b
        return res
       return inner
ret = wrapper(2,3)
print(ret.__code__.co_freevars)    # ('a', 'b')

装饰器

装饰器:在不改变 原函数代码 以及 调用方式 的前提下,为其增加新的功能
import time
def index():
    time.sleep(2)
    print('welcom login')    # 模拟登陆
def timmer(f):    # 这里用到了闭包。这里f是个自用变量,自由变量不受函数外部影响
    def inner():
        start_time = time.time()
        f()
        end_time = time.time()
        print(f'测试函数的执行效率{end_time-start_time}')
    return inner
index = timmer(index)    # 将函数名index作为参数传递给timmer(f),实际上传递的是index指向的内存地址,即 变量f指向了index指向的内存地址。然后将返回值inner重新赋值给index,index指向的内存地址变成了inner()函数的内存地址
index()

# 语法糖:@,用来当做装饰器装饰函数 ,@timmer()相当于 index = timmer(index)
import time
def timmer(f):
    def inner():
        start_time = time.time()
        f()
        end_time = time.time()
        print(f'测试函数的执行效率{end_time-start_time}')
    return inner
@timmer        # 代码执行到这里的时候,会向下多执行一行
def index():
    time.sleep(2)
    print('welcome login')
index()


#带参数有返回值的装饰器
import time
def timmer(f):
    def inner(*args,**kwargs):
        st = time.time()
        ret = f(*args,**kwargs)
        et = time.time()
        print(f'login application run time{et - st}')
        return ret
    return inner
@timmer
def login(name):
    time.sleep(1)
    print(f'welcome to blog,{name}!!')
login('alex')


#标准版的装饰器
def wrapper(f):
    def inner(*args,**kwargs):
        ''' 添加额外功能,执行被装饰函数之前的操作'''
        ret = f(*args,**kwargs)
        '''添加额外功能,执行被装饰函数之后的操作'''
        return ret
    return inner


# 通过改变一个参数,控制代码是否执行
import time
def change_start(a):
    def wrapper(f):
        def inner(*args,**kwargs):
            if a:
                st = time.time()
                ret = f(*args,**kwargs)
                et = time.time()
                ti = et - st
                return ti
            else:return 'no run'
        return inner
    return wrapper
@change_start(False)    # 这里传递参数,来控制被装饰函数是否执行
def login():
    time.sleep(1)
print(login())
原文地址:https://www.cnblogs.com/jmuchen/p/13418420.html