闭包函数和装饰器

今日学习的内容:闭包函数、装饰器。

闭包函数

闭包函数就是两个函数的嵌套,两个函数分为内部函数和外部函数,当外部函数的返回值是内部函数的引用的时候,就构成了闭包的情况。

def func():  # 外部函数
    name = 'jason' 
    def inner():  # 内部函数
        print(name)  # 内部函数的执行
    return inner  # 返回值为内部函数

f = func()  # 外部函数引用了内部函数
f()

 闭包函数要满足一下两点:

1、定义在函数内部的函数。

2、内部函数引用外部函数名称空间作用域的名字。

要点:函数在定义阶段名字的查找顺序就已经固定死了,不会因为函数调用位置的变化而改变。

给函数传参会用到的两种方式:
1、直接传参
    def index(name):
          print(name)

2、闭包
    def outter(name):
          name = 'jason'
          def index():
                print(name)
          return index

 装饰器

装饰器的作用是给被装饰的对象添加新的功能。

装饰器的开放封闭原则:开放(对扩展开放)、封闭(对修改封闭)

装饰器(调用对象)必须遵循的两个原则:

1.不改变被装饰对象的源代码

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

#小知识点
import time
print(time.time())  # 时间戳,显示的是当前时间距离1970-1-1 00:00:00相差的秒数

time sleep(3)  # 让你的程序暂停3秒再执行
print('NB')

我们先写一个函数

import time
def index():
    time.sleep(3)
    print('时间到了,gogogo!')
print(index())

我们要添加一个功能,用来统计index函数执行的时间

start = time.time()  # 记录index开始的时间
index()
end = time.time()  # 记录index结束的时间
print('index run time:%s'%(end-start))  # 打印出运行index()的时间

我们把这个功能写到一个函数里面然后要让我们在直接调用index()的时候能加入这个

import time
def index():
    time.sleep(3)
    print('时间到了,go go go!')

def outter(func):  # func = 最原始的index函数的内存地址
    def get_time():
        start = time.time()
        func()  # func = index函数的内存地址() 直接调用
        end = time.time()
        print('index run time:%s'%(end-start))
    return get_time
index = outter(index)  # outter(最原始的index函数内存地址),本质上返回了get_time
# index指向get_time函数的内存地址
index()  #本质上调用了get_time函数,get_time()中的func()才调用的是原函数

我们通过命名了一个与index()同名的变量名达到了目地,接下来要让它的返回值也与index()相同。

import time
def index():
    time.sleep(3)
    print('时间到了,go go go!')
    return 'index'
def outter(func):  # func = 最原始的index函数的内存地址
    def get_time(*args, **kwargs):  # args = ('egon',) kwargs = {}
        start = time.time()
        res = func(*args, **kwargs)  # 最原始的index函数的内存地址() 直接调用  
        end = time.time()
        print('func run time:%s'%(end-start))
        return res
    return get_time
index=outter(index)  
print(index())

pychram中的语法糖

@outter  # index = outter(index)  outter(最原始的index的函数的内存地址)
def index():
    time.sleep(3)
    print('时间到了,go go go!') 
    return 'index'

@outter就是语法糖,在@的后面就是你装饰器的最外层的函数名,然后语法糖会把紧挨着它的下面的函数名当做参数进行调用

装饰器修复技术

from functools import wraps
def outter(func):
    @wraps(func)  # 装饰器修复技术,加载内层函数的正上方
    def inner(*args,**kwargs):

在加入了装饰器修复技术后用户查看到的就是被装饰函数的本身,而且查看到的注释也是被装饰函数本身的注释。

装饰器的模板

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


2.有参装饰器(最复杂就三层)
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/wangnanfei/p/11173240.html