python基础语法7 闭包函数与装饰器

时间:2019-11-12
本文章向大家介绍python基础语法7 闭包函数与装饰器,主要包括python基础语法7 闭包函数与装饰器使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

闭包函数:
  1.闭包函数必须在函数内部定义
  2.闭包函数可以引用外层函数的名字

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

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

func(1000)


# 通过闭包函数传参
def outer(number):
    # number = 100
    # inner就是闭包函数
    def inner():
        print(number)
    return inner

func = outer(1000)  # ---》 inner地址 ---》 func变量名
func()  # func ---> inner地址()

闭包函数的应用

# 方式一: 直接传参
def spider_func(url):
    # 往url地址发送请求,获取响应数据
    response = requests.get(url)  # 必须接受url
    # 状态码: 200
    if response.status_code == 200:
        # 获取当前url地址中所有的文本
        print(len(response.text))
        print(response.text)
url = 'https://www.cnblogs.com/xiaoyuanqujing/'
spider_func(url)
——————————————————————————
# 方式二: 通过闭包函数接受url地址,执行爬取函数
def spider_outer(url):
    # url = 'https://www.cnblogs.com/xiaoyuanqujing/'
    def spider_inner():
        response = requests.get(url)
        if response.status_code == 200:
            print(len(response.text))
    return spider_inner


# 爬取 小猿取经
spider_blog = spider_outer('https://www.cnblogs.com/xiaoyuanqujing/')
spider_blog()
# 爬取 京东
spider_baidu = spider_outer('https://www.baidu.com/')
spider_baidu()

装饰器:

  不修改被装饰对象的源代码  
  不修改被装饰对象的调用方式

  被装饰对象: ---> 需要添加功能 函数
  装饰器: ---> 被装饰对象添加的新功能的 函数

  time_record ---》 装饰器

需求: 统计下载电影函数的运行时间。

# 下载电影功能(初始代码)
def download_movie():
    print('开始下载电影...')
    # 模拟电影下载时间 3秒
    time.sleep(3)  # 等待3秒
    print('电影下载成功...')
    return 'sean与jason的雨后的小故事.mp4'


start_time = time.time()  # 获取当前时间戳
download_movie()
end_time = time.time()  # 获取当前时间戳
print(f'消耗时间: {end_time - start_time}')
# 问题: 多个被装饰对象,需要写多次统计时间的代码,导致代码冗余。
# 装饰器: 初级版
def time_record(func):
    def inner(*args, **kwargs):
        # 统计开始
        start_time = time.time()

        # 被装饰对象, 问题1: 有返回值, 问题2: 不确定参数的 个数
        res = func(*args, **kwargs)  # func() ---> download_movie()
        # 当被统计的函数执行完毕后,获取当前时间
        end_time = time.time()
        # 统计结束,打印统计时间
        print(f'消耗时间: {end_time - start_time}')

        return res

    return inner


download_movie = time_record(download_movie)  # inner
# name = 'egon'
# download_movie(name)
download_movie(name='egon')



# inner()  #  inner() ---> download_movie()

# download_movie = time_record(download_movie)  # inner


# download_movie()  #  download_movie() ---> download_movie()
# 问题1: 被装饰对象 有返回值


# 下载电影功能
def download_movie():
    print('开始下载电影...')
    # 模拟电影下载时间 3秒
    time.sleep(3)  # 等待3秒
    print('电影下载成功...')
    return '小泽.mp4'


def time_record(func):  # func <-- download_movie

    # 在闭包函数中
    def inner():
        # 统计开始
        start_time = time.time()
        res = func()  # func() ---> download_movie()
        # 当被统计的函数执行完毕后,获取当前时间
        end_time = time.time()
        # 统计结束,打印统计时间
        print(f'消耗时间: {end_time - start_time}')

        return res

    return inner


download_movie = time_record(download_movie)
download_movie()
#问题2: 被装饰对象 有参数
#下载电影功能
import time
def download_movie(url):
    print(f'{url}中的电影开始下载了...')
    # 模拟电影下载时间 3秒
    time.sleep(3)  # 等待3秒
    print('电影下载成功...')
    return '小泽.mp4'


def time_record(func):  # func <-- download_movie
    # url = 'https://www.baidu.com/'

    # 在闭包函数中
    def inner(url):
        # 统计开始
        start_time = time.time()

        res = func(url)  # func(url) ---> download_movie(url)

        # 当被统计的函数执行完毕后,获取当前时间
        end_time = time.time()
        # 统计结束,打印统计时间
        print(f'消耗时间: {end_time - start_time}')
        return res
    return inner

download_movie = time_record(download_movie)

download_movie(url) --> inner(url)
download_movie('https://www.baidu.com')
#问题4: 假如被装饰对象需要接收多个参数
def download_movie(url, url2, url3):
    print(f'{url}中的电影开始下载了...')
    # 模拟电影下载时间 3秒
    time.sleep(3)  # 等待3秒
    print('电影下载成功...')
    return '小泽.mp4'

def download_movie():
    print('电影开始下载...')
    # 模拟电影下载时间 3秒
    time.sleep(3)  # 等待3秒
    print('电影下载成功...')
    return '小泽.mp4'
# 装饰器最终版本
def time_record(func):  # func <-- download_movie
    # 在闭包函数中
    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'消耗时间: {end_time - start_time}')

        return res
    return inner

# download_movie = time_record(download_movie)
#
# download_movie()
# download_movie(url) --> inner(url, url2, url3)
# download_movie(url1='https://www.baidu.com', url2='url2', url3='url3')
# 装饰器模板:权限设定
# 装饰器最终版本
def wrapper(func):

    def inner(*args, **kwargs):

        # 让用户输入内容
        username = input('请输入名字')

        if username == 'tank':
            # 调用被装饰对象,得到返回值
            res = func(*args, **kwargs)
            return res

        else:
            print('用户权限不足!')

    return inner

def func1():
    pass

func1 = wrapper(func1)
func1()  # inner()

装饰器的语法糖,是属于装饰器的。
@: 装饰器的语法糖

# 注意: 在使用装饰器语法糖时,装饰器必须定义在被装饰对象之上

import time

# 统计函数执行时间装饰器
def wrapper(func):  # 被装饰对象
    def inner(*args, **kwargs):  # 被装饰对象的参数
        # 调用前增加新功能
        start_time = time.time()
        # 调用被装饰对象,并接收返回值
        res = func(*args, **kwargs)

        # 调用后添加新功能
        end_time = time.time()
        print(end_time - start_time)

        return res
    return inner

# func函数需要执行3秒

# 无参装饰器
# 使用装饰器
@wrapper  # wrapper(func)  ---> func
def func():

    time.sleep(3)

func()

原文地址:https://www.cnblogs.com/ludingchao/p/11844921.html