Python学习----闭包和装饰器

news2024/9/25 11:20:47

情景:
当我们调用函数的时候,函数调用完成之后,函数内定义的变量都会被销毁,但是我们有时候需要保存函数内的这个变量,每次在这个变量的基础上完成一系列的操作,比如:每次在这个变量的基础上和其他数字进行求和计算。

我们可以通过闭包来实现这个问题。

闭包作用:

闭包可以保存函数内的变量,不会随着函数调用完成而销毁。

闭包的定义

在函数嵌套调用的前提下,内部函数使用了外部函数的变量,并且外部函数返回了内部函数,我们把这个使用外部函数的内部函数称为闭包。

闭包构成条件:
1、在函数嵌套的前提下
2、内部函数使用了外部函数的变量(还包括外部函数的参数)
3、外部函数返回了内部函数
结论:闭包可以对外部函数的变量进行保存
在这里插入图片描述

闭包内修改外部变量

def func_out(num1):
	def func_inner(num2):
		num1 = num2 + 10
	return func_inner

问题:在func内中的num1,能否通过func_inner内的 num1=num2+10 进行修改
通过下面代码演示可以看出,inner内部的num1 相当于在inner作用域内重新定义了一个变量num1,是不会影响外部函数out的num1的。
使用 nonlocal关键字,可以在内部函数使用外部函数的参数。
和global关键一样,在函数内部使用全局变量。
在这里插入图片描述
使用nonlocal关键字之后
在这里插入图片描述


装饰器的作用

在不改变原有函数的源代码的情况下,给函数增加新的功能

装饰器的功能特点:
1、不修改已有函数的源代码
2、给已有函数增加额外的功能

装饰器使用步骤

1、定义一个装饰器(装饰器的本质是闭包)
2、使用装饰器装饰函数
在这里插入图片描述
自己总结:因为闭包,在内部函数里面使用了外部函数的参数,所以在外部函数使用结束之后,因为内部函数引用的关系,外部函数的参数并不会消失。
现在将需要被装饰的函数(源函数),作为外部函数的参数传入,在内部函数里面对 源函数 进行代码增强并且调用源函数。
这样子,就达到了不修改 原函数 但是起到了增加额外功能的目的。

语法糖简化代码
# comment = check(comment)
# 解释器遇到@check 会立即执行comment = check(comment)
@check
def comment():
	print("发表评论")

装饰器使用实例

获得函数执行时间
这个装饰器可以在任意函数进行使用,代码复用性大大提高

import time

# 定义装饰器
def get_time(fn):
    def inner():
        start_time = time.time()
        fn()
        enn_time = time.time()
        print("时间:", enn_time - start_time)

    return inner

# 被装饰的函数
@get_time
def func():
    for i in range(100000):
        print(i)


func()

装饰带有参数的函数
最后结论就是:inner参数要和被装饰的函数保质一致,因为最终返回的是inner
在这里插入图片描述

装饰带有返回值的函数
只要你明白上面的了,就可以举一反三明白下面的, inner 对标 被装饰后的,那么你装饰之前有什么,就在inner里面补什么。
在这里插入图片描述

装饰带有不定长参数的函数
和第一个装饰带有参数的是同样的道理
在这里插入图片描述

通用装饰器

def logging(fn):  # fn = sum_num
    def inner(*args, **kwargs):
        print("装饰代码")
        return fn(*args, **kwargs)

    return inner


@logging  # sum_num = logging(sum_num) ; 所以现在sum_num  = inner
def sum_num(*args, **kwargs):
    print(args)
    print(kwargs)
    return None


print("装饰之后:", sum_num(1, 2, 3, 4, 5, 6, age=19))

多个装饰器的使用

# 装饰器1
def check1(fn):
    def inner():
        print("登录验证1")
        fn()

    return inner


# 装饰器2
def check2(fn):
    def inner():
        print("登录验证2")
        fn()

    return inner


# 需要被装饰的函数
# 装饰顺序和语法糖位置写的位置一致
@check2
@check1
def comment():
    print("发表评论")

comment()

带有参数的装饰器

语法规则:装饰器的外部函数只能有一个参数,闭包不存在这个规则,只针对装饰器
但是哈,只是针对语法糖的规则
在这里插入图片描述
你不是用语法糖,上面语法规则不成立
在这里插入图片描述

如果你要使用语法糖进行传参数,那就只能多包一层。我觉得这个很鸡肋,还不如不使用语法糖
第一个@logging 第一层根本没有起到装饰器作用,外层的只是起到一个传参作用。因为add函数没有作为它的参数,虽然logging任然是闭包,但是针对add函数来说,logging作用只是传参,针对 flag函数来说,logging函数是闭包。(完美理解)
add = logging(“+”) = decorator(add) = inner(num1,num2)
在这里插入图片描述

类装饰器

__call__的使用
一旦一个类里面实现了 call方法,那么这个类创建的对象就是一个可调用对象,可以像调用函数一样进行调用。
在这里插入图片描述
类装饰器的实现,这个使用比较少,我感觉不好,和java相比,你这个类型都变了
在这里插入图片描述
同样语法糖规则也适用,comment已经变成了一个类
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/78600.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【全网惟一面向软件测试人员的Python基础教程】- 学Python之前要搞懂的道理

全网惟一面向软件测试人员的Python基础教程 起点:《python软件测试实战宝典》介绍 第一章 为什么软件测试人员要学习Python 第二章 学Python之前要搞懂的道理 文章目录全网惟一面向软件测试人员的Python基础教程计算机的本质是什么?什么是编程呢&#x…

Java泛型的使用和原理

文章目录泛型-概述基础使用泛型类的使用泛型类派生子类泛型接口泛型方法类型通配符类型通配符上限类型通配符下限常用泛型标识符类型擦除使用注意泛型与数组泛型和反射其他泛型-概述 Java 泛型(generics)是 JDK 5 中引入的一个新特性,泛型提…

第十四届蓝桥杯集训——JavaC组第八篇——进制转换

第十四届蓝桥杯集训——JavaC组第八篇——进制转换 目录 第十四届蓝桥杯集训——JavaC组第八篇——进制转换 短除法 十进制转二进制示例: 十进制转换二进制 十进制转换八进制 十进制转换十六进制 二进制转十进制 八进制转十进制 十六进制转十进制 进制转换…

【✨十五天搞定电工基础】半导体器件

本章要求1. 理解PN结的单向导电性,三极管的电流分配和电流放大作用 2. 了解二极管、稳压管和三极管的基本构造、工作原理和特性曲线,理解主要参数的意义 3. 会分析含有二极管的电路 目录 一、半导体基础知识 1、本征半导体的导电机理 2、杂质半导体 …

部分核心技术(持续更新)

文章目录1.Schedule(定时任务)2.高并发线程安全的解决方案2.1为什么不适用同步锁(Synchronized)?2.2 Redis的分布式锁setnx2.3 redisson分布式锁(看门狗机制)2.3.1 Redis的分布式锁setnx产生的问…

保姆级入门nest笔记

使用 NEXT 搭建后台服务接口 https://docs.nestjs.com/ # 准备工作 安装 node 全局安装 nest npm i -给nestjs/cli nest --version # 创建项目 创建项目next new 启动项目npm run start 或 npm run start:dev 访问接口 localhost:3000 获取命令解释 next g -h # 快速创建…

Pixracer接线图 及电调调参 BLheliSuite

Pixracer接线指南 pixracer官方链接 正反面引脚定义 接口含义 BLheliSuite调参软件 官方下载: https://www.mediafire.com/folder/dx6kfaasyo24l/BLHeliSuite 我使用了如下软件https://www.mediafire.com/file/9uccf1zy3wqb1w5/BLHeliSuite32_32.9.0.3.zip/fil…

Bio-Net:编解码器结构的循环双向连接网络

目录 摘要 方法 循环双向跳跃连接 前向跳跃连接 后向跳跃连接 递归的推断训练 BiO-Net网络结构 总结 摘要 对UNet以前的扩展主要集中对现有模块的改进或者提出新的模块来提高性能。因此这些变量通常会导致模型的复杂性不可忽视的增加。为了解决这种复杂性的问题。在本…

redis cluster 集群安装

redis cluster 集群安装 redis集群方案 哨兵集群 如图,实际上还是一个节点对外提供服务,所以虽然是三台机器,但是还是一台机器的并发量,而且master挂了之后,整个集群不能对外提供服务 cluster集群 多个主从集群节点…

五、伊森商城 前端基础-Vue 整合ElementUI快速开发 p28

目录 一、安装 1、安装ElementUI 2、在main.js文件中引入 2.1、引入ElementUI组件 2.2、让Vue使用ElementUI组件 二、使用 1、在hello.vue组件使用单选框 2、使用ElementUI快速搭建后台管理系统 2.1、修改App.vue 3、修改功能成动态显示 3.1、编写快速生成组件的模板 3…

java计算机毕业设计ssm学习互助平台网站8f554(附源码、数据库)

java计算机毕业设计ssm学习互助平台网站8f554(附源码、数据库) 项目运行 环境配置: Jdk1.8 Tomcat8.5 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff0…

C++11之引用

文章目录目的为啥要引入右值引用什么是右值引用右值引用作用移动构造函数移动语义 std::move移动语义注意事项完美转发博客目的 了解对应左值引用, 右值引用,移动语义, 完美转发含义。 右值引用(及其支持的移动语义Move semanti…

1562_AURIX_TC275_电源监控

全部学习汇总: GreyZhang/g_TC275: happy hacking for TC275! (github.com) 这一次的学习笔记内容比较少,因为有几页的文档内容跟之前看过的DataSheet内容雷同。因此,相应的学习笔记不再整理。 之前的学习笔记: (56条消息) 1451_…

Python学习基础笔记四十——os模块

os模块是与操作系统交互的一个接口。 os的方法Linux命令备注os.getcwd()pwd获取当前工作目录路径os.chdir()cd切换当前工作目录os.makedirs(dirname1/dirname2)mkdir -p dirname1/dirname2生成多级目录os.removedirs(dirname1)rmdir删除多级目录os.mkdir(dirname)mkdir dirnam…

JAVA入门零基础小白教程day04-数组

day04_java基础 课程目标 1. 【掌握】 IDEA的基本使用 2. 【理解】 什么是数组 3. 【掌握】 数组的定义及初始化 4. 【理解】 数组的内存图 6. 【理解】 数组常见的问题 7. 【掌握】 数组的案例 8. 【理解】 二维数组开发工具 一维数组 什么是数组 数组就是存储数据长度固定…

【Linux】源码安装Apache、Mysql、PHP以及LAMP部署验证

文章目录源码安装相关理论源代码安装特点源码包安装步骤一、源码安装Apache1、编译安装依赖包 apr2、编译安装依赖包 apr-util3、编译安装依赖包 pcre4、编译安装 Apache5、重启 apache 服务6、修改网页显示内容7、访问测试二、源码安装Mysql1、把系统自带的 boost 库卸载&…

【mmdetection系列】mmdetection之loss讲解

目录 1.configs 2.具体实现 3.调用 3.1 注册 3.2 调用 配置部分在configs/_base_/models目录下,具体实现在mmdet/models/loss目录下。 1.configs 有的时候写在head中作为参数,有的时候head内部进行默认调用。 我们以为例(这里没有直接…

linux timer浅析

linux timer 1、数据结构 1.1 timer_list struct timer_list {struct hlist_node entry;unsigned long expires;void (*function)(struct timer_list *);u32 flags;#ifdef CONFIG_LOCKDEPstruct lockdep_map lockdep_map; #endif };entry:定时器保存到哈希表中的节点&am…

QT+Python停车场车牌识别计费管理系统

程序示例精选 Python停车场车牌识别计费管理系统 如需安装运行环境或远程调试,见文章底部微信名片! 前言 QTPython是非常经典的窗体编程组合,功能完善,可视化界面美观易维护,这篇博客针对停车场车牌识别计费方面编写代…

JavaScript前端实用的工具函数封装

这篇文章主要为大家介绍了JavaScript前端实用的一些工具函数的封装,有需要的朋友可以借鉴参考下,希望能够有所帮助! 1.webpack里面配置自动注册组件 第一个参数是匹配路径,第二个是深度匹配,第三个是匹配规则 const requireComponent require.contex…