闭包函数和装饰器

闭包函数

  什么是闭包函数:内部函数对外部函数作用域而非全局全局作用域中的变量引用,那么该函数就叫闭包函数

  (闭包函数必须定义在函数内部,可以使用外层函数的名字)

    闭包函数是函数嵌套,函数对象,名称空间与作用域的结合体

#直接传参
def func(number):
    print(number)


func(10)
>>10


#通过闭包传参
def outer(number):
    def inner(): #inner闭包函数
        print(number)
    return inner #将inner当做参数返回


inner = outer(10)
inner()
>>10

闭包函数的应用:  为了装饰器做准备

函数体传值的方式:1.直接将值以参数的形式传入;2.将值包给函数

例子:  

  爬取某个网站,打印获取数据的长度

# 方式一 直接传参
import requests


def spider_func(url):
    # 往url地址发送请求,获取响应数据
    response = requests.get(url) # 必须接收url
    # 状态码 200
    if response.status_code == 200:
        #获取当前url地址中文本长度
        print(len(response.text))
        #获取当前url地址所有文本
        print(response.text)
        print(response.status_code)


url = 'https://www.baidu.com'
spider_func(url)
#方式二 通过闭包函数接受url地址,执行爬取函数
import requests


def spider_func(url):
    def spider_inner():
        response = requests.get(url)
        if response.status_code == 200:
            print(len(response.text))
    return spider_inner


spider_page = spider_func('https://www.baidu.com/')
spider_page()

装饰器:装饰的工具

  装饰器必须要遵循“开放封闭”原则

    开放:对函数功能的添加是开放的

    封闭:对函数功能的修改是封闭的

  装饰器的作用:在不修改被装饰对象源代码与调用方式的前提下,添加新的功能

  装饰器必须遵循:*不修改被装饰对象源代码  *不修改被装饰对象的调用方式

  怎么使用装饰器:

    装饰器的应用:*统计时间 *登录认证......

  为什么使用装饰器:可以解决代码冗余,提高代码的可扩展性

  编写编写装饰器:通过闭包函数编写

例子:

  需求:统计电影的下载时间

import time


def movie_download():
    print('start download')
    time.sleep(3)
    print('download completed')
    return 'nmb'


# start_time = time.time()
# movie_download()
# end_time = time.time()
# print(f'time cost:{end_time-start_time}')
#缺点:当有多个装饰对象时,需要编写多次统计时间代码,导致代码冗余



# 添加计时功能
def time_record(func):
    start_time = time.time()
    # movie_download()   若这么写 该功能只能给movie_download()使用
    func()
    end_time = time.time()
    print(f'time cost:{end_time - start_time}')
    return None

res = time_record(movie_download)
print(res)

完善装饰器

import time


def time_record(func):
    def inner(*args,**kwargs): # *args, **kwargs接收所有参数
        start_time = time.time()
        # 将被装饰对象需要接收的任意参数 原封不动传给func --》 被装饰对象
        res = func(*args,**kwargs) # func(url) ---> download_movie(url)
        end_time = time.time()
        print(f'time cost:{end_time-start_time}')
        return res
    return inner

def movie_download():
    print('start download')
    time.sleep(3)
    print('download completed')
    return 'nmb'


movie_download = time_record(movie_download)
movie_download()

装饰器语法糖:

  在使用语法糖时,装饰器必须在被装饰对象前定义

  

import time


def wrapper(func):
    def inner(*args,**kwargs):
        start_time = time.time()
        res = func(*args,**kwargs)
        end_time = time.time()
        print(f'{end_time-start_time}')
        return res
    return inner

# 使用装饰器语法糖
@wrapper
def func():
    print('start')
    time.sleep(3)
    print('end')
func()

# 不使用语法糖
func = wrapper(func)
func()

装饰器模板

def wrapper(func):
    def inner(*args,**kwargs):
        #功能输入区
        
        res = func(*args,**kwargs) # 调用被装饰对象,得到返回值
        
        #功能输入区
        return res
    return inner

def func():
    pass

func = wrapper(func)
func()
原文地址:https://www.cnblogs.com/littleb/p/11842211.html