【Python】Python函数的黑魔法:递归,嵌套函数与装饰器

欢迎来到CILMY23的博客

本篇主题为: Python函数的黑魔法:递归,嵌套函数与装饰器

个人主页:CILMY23-CSDN博客

系列专栏:Python | C++ | C语言 | 数据结构与算法

感谢观看,支持的可以给个一键三连,点赞关注+收藏。


写在前头:

本期主要补充上篇未完成的内容,(点击链接跳转)其中包括参数传递中序列解包,递归函数和嵌套函数,以及python中重要的概念————装饰器 ,除此之外还会扩展一些python中的作用域概念


目录

一、参数传递的序列解包

二、递归函数和嵌套函数

2.1 递归函数

2.2 嵌套函数

三、装饰器

3.1 装饰器的概念

3.2 装饰器的定义和使用

3.3 装饰器的应用场景

四、变量的作用域

4.1 变量类型

4.2 global关键字和nonlocal

global关键字

nonlocal关键字


一、参数传递的序列解包

参数传递的序列解包是指在函数调用时,将一个序列(如列表、元组等)进行解包,然后将解包后的内容作为参数传递给函数。这使得我们可以使用序列中的元素来作为函数的参数,而不必一个个地手动传递。

例如:

def func(x,y,z):return x + y +zprint(func(*[1,2,3]))
print(func(*(5,9,8)))

我们在上一篇中说,* args是将接收的多个参数放在一个元组里,那 * 其实是将一个序列中的元素解包出来,分别传递给形参中的各个变量。那 ** 就是将字典的各个元素传递给形参中的多个变量

 例如:

# 定义函数2
def func2(name, age):print(f"Name: {name}, Age: {age}")# 创建人的字典
person = {'name': 'Alice', 'age': 25}# 将字典通过**解包传递给函数2
func2(**person)

注意:字典中的"键---值"和形参在名称和个数必须一一对应 

二、递归函数和嵌套函数

 递归函数和嵌套函数,它们都是 Python 编程中非常重要的概念,接下来我们就详细看看吧

2.1 递归函数

如果一个函数在函数体中直接或间接调用自身,那么这个函数就被称为递归函数。简单来说,这个函数在调用的时候会调用自身,直到结束。

Python允许使用递归函数。如果函数 a 中调用函数 a 自身,则称为直接递归。如果函数 a 在内部调用了函数 b,在函数 b 中又调用函数 a,则称为间接递归

递归函数的思想是"将一个大问题分解为一个或多个与原问题形式相似但规模较小的子问题来解决"。函数会不断地调用自身来解决这些子问题,直到达到了结束条件,从而结束递归的过程。

例如:求斐波那契数列前十项

# 递归函数
def Fib(n):if n < 2:return 1  # 第1,2个斐波那契数为1else:return Fib(n-1) + Fib(n-2)  # 递推关系:前两个斐波那契数之和# 输出前10个斐波那契数
for i in range(10):print(Fib(i),end=" ")

结果: 

 

解析:

当使用递归函数来解决斐波那契数列时,可以通过递归的方式来计算第n个斐波那契数。斐波那契数列的定义如下:

  • 第1个斐波那契数为1
  • 第2个斐波那契数为1
  • 从第2个数开始,后续的每个斐波那契数都是前两个斐波那契数之和

练习题:使用递归函数解决1+2+……+n的和。(答案在文章末尾) 

2.2 嵌套函数

嵌套函数指的是在一个函数内部定义另一个函数。其中,外部定义函数称为外函数,内部定义的函数称为内函数,嵌套函数在外部函数中具有局部作用域,它可以访问外部函数的变量。

例如:

# 嵌套函数
def outer_function(x):def inner_function(y):return y * 2return inner_function(x)  # 调用内部函数result = outer_function(5)  # 调用外部函数
print(result)  # 输出 10

三、装饰器

装饰器是一种Python编程语言的特性,那具体的我们接着往下看吧

3.1 装饰器的概念

装饰器(Decorator)是用来包装函数的函数。装饰器是一种语法,允许在不修改函数原始代码的情况下,动态地添加功能或修改函数的行为。

装饰器基于函数,基本原理是将一个函数作为参数传递给另一个函数,然后返回一个新的函数。这个新函数通常用来包裹原始函数,并在执行原始函数前后执行一些额外的代码。

3.2 装饰器的定义和使用

定义装饰器的一般格式为:

def decorator(func):pass@decorator
def func():pass

其中,decorator 为装饰器。@decorator 为函数的装饰器修饰符。func 为装饰器的函数对象参数。装饰器可以返回一个值,也可以返回一个函数,还可以返回一个装饰器或其他对象。

例如:装饰器返回一个函数

# 装饰器返回一个函数
def my_decorator(func):def wrapper():return func() + 1return wrapperdef my_function():return 3my_function = my_decorator(my_function)result = my_function()
print(result)  # 输出 4

 代码解析:

当调用 my_function() 时,实际上我们是在用装饰器 my_decorator,而 my_function 替代了 func

装饰器中嵌套了 wrapper() 函数,并且返回值是 wrapper ,所以实际上我们就是调用了 wrapper()这个函数,并将这个函数的返回值作为装饰器的返回值传递。

所以计算就是 3+1 = 4

 例如:装饰器返回一个装饰器

# 装饰器返回一个装饰器
def outer_decorator(option):if option == "A":def inner_decorator(func):def wrapper():return func()return wrapperelif option == "B":def inner_decorator(func):def wrapper():return func()return wrapperelse:raise ValueError("Invalid option")return inner_decorator@outer_decorator(option="A")
def ret1():return "Hello, world!"@outer_decorator(option="B")
def ret2():return "Hello again!"print(ret1())
print(ret2())

 代码解析:

外部装饰器 outer_decorator 会根据 option 的不同,选择不同的装饰器 inner_decorator(func),然后将外部函数替换掉 func , 最后返回装饰器 inner_decorator,像上述案例,如果有装饰器嵌套装饰器,就被称为多重装饰器

3.3 装饰器的应用场景

 例如:修改网页的文本格式

# 修改网页的文本格式
# 定义装饰器
def deco(func):# 定义内函数def modify_text(str):return "<strong>" + func(str) + "</strong>"return modify_text# 使用装饰器修饰函数
@deco
def textFunc(str):return strprint(textFunc("text"))

四、变量的作用域

4.1 变量类型

  1. 局部变量和局部作用域 L(Local):定义在函数内部的变量。局部变量的作用域是从函数内定义它的位置到结束。当函数被调用时创建一个新的局部变量,函数调用完成后,局部变量就消失了。

  2. 全局变量和全局作用域G(Global):在模块的函数外定义的变量。在模块文件顶层声明的变量具有全局作用域。从外部看,模块的全局变量就是一个模块对象的属性。全局作用域的作用范围仅限于单个模块文件内。

  3. 嵌套变量和嵌套作用域E(Enclosing):定义在嵌套函数的外函数内、内函数外的变量。嵌套作用域为嵌套函数内定义它的位置开始的整个函数内。

  4. 内建变量和内建作用域B(Built-in):系统内固定模块里定义的变量,一般为预定义在内建模块内的变量。

例如:

# 四、变量作用域
global_v = "我是一个全局变量"def outer_function():enclosing_v = "我是一个嵌套变量"def inner_function():local_v = "我是一个局部变量"print(local_v)print(enclosing_v)print(global_v)inner_function()outer_function()
print(global_v)

 在Python中,当程序执行中要使用一个语句中的变量时,就会按照 L -> E -> G -> B 的规则在程序中查找这个变量的定义,即在局部范围中找不到,便会去局部范围外查找,然后去全局变量以此类推。

4.2 global关键字和nonlocal

global关键字

当在函数内部想要修改全局作用域的变量时,可以使用global关键字来声明变量。这样就可以在函数内部修改全局变量的值。

# global 关键字global_var = 10def modify_global():global global_varglobal_var = 20modify_global()
print(global_var)  # 输出 20

结果:打印20 

nonlocal关键字

nonlocal关键字用于在一个嵌套函数中修改嵌套作用域 E 的变量。当在内部函数中想要修改上一层函数中的变量时,可以使用nonlocal关键字。

# nonlocal 关键字
def outer_function():outer_var = 10def inner_function():nonlocal outer_varouter_var = 20inner_function()print(outer_var)  outer_function()

 结果:输出20


   总结:

  • * 用于序列解包,** 用于字典解包
  • 递归函数的核心是将一个大问题拆解成无数子问题
  • 装饰器本质上是一个函数,它接受一个函数作为参数,并返回一个新的函数。
  • 装饰器也可以嵌套装饰器,从而选择不同的效果

感谢各位同伴的支持,本期python篇就讲解到这啦,如果你觉得写的不错的话,可以给个一键三连,点赞关注+收藏,若有不足,欢迎各位在评论区讨论。 

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

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

相关文章

基于51单片机的矩阵按键扫描的proteus仿真

文章目录 一、按键按键按键消抖 二、独立按键仿真图仿真程序 三、矩阵按键仿真图仿真程序 四、总结 一、按键 按键 按键通常指的是电子设备上的一种输入装置&#xff0c;用于在按下时发送信号&#xff0c;以便设备执行相应的操作。按键可以分为独立按键和矩阵按键两种类型。 …

TRIZ理论下攀爬机器人的创新设计与研究

随着科技的飞速发展&#xff0c;机器人技术已广泛应用于各个领域。特别是在复杂环境下的作业&#xff0c;如灾难救援、太空探测等&#xff0c;对机器人的移动能力和适应性提出了更高要求。在这样的背景下&#xff0c;基于TRIZ理论的攀爬机器人设计与研究应运而生&#xff0c;它…

简单的图像处理算法

本笔记参考crazy_Bingo 基础&#xff1a; 图像处理都是用卷积矩阵对图像卷积计算&#xff0c;如3X3 的矩阵对640 X 480分辨率的图像卷积&#xff0c;最终会得到638 X 478 的图像。卷积过程是这样的&#xff1a; 一、中值滤波 &#xff1a; 找出矩阵中的最中间值作为像素点 中…

Flink的安装、项目创建、任务打包和部署完整实现,任务实现使用JAVA语言

Flink资源下载地址 Flink安装包下载地址 一、本地模式安装Flink 1、在Linux服务上&#xff0c;创建flink文件夹 mkdir flink 2、上传文件并解压 tar -zxvf flink-1.14.6-bin-scala_2.11.tgz 解压完成后&#xff0c;如图&#xff1a; 3、启动Flink 进入到解压目录下&#x…

YOLOv9训练损失、精度、mAP绘图功能 | 支持多结果对比,多结果绘在一个图片(消融实验、科研必备)

一、本文介绍 本文给大家带来的是YOLOv9系列的绘图功能&#xff0c;我将向大家介绍YOLO系列的绘图功能。我们在进行实验时&#xff0c;经常需要比较多个结果&#xff0c;针对这一问题&#xff0c;我写了点代码来解决这个问题&#xff0c;它可以根据训练结果绘制损失(loss)和mA…

Java的八大基本数据类型和 println 的介绍

前言 如果你有C语言的基础&#xff0c;这部分内容就会很简单&#xff0c;但是会有所不同~~ 这是我将要提到的八大基本数据类型&#xff1a; 注意&#xff0c;Java的数据类型是有符号的&#xff01;&#xff01;&#xff01;和C语言不同&#xff0c;Java不存在无符号的数据。 整…

Day:动态规划 LeedCode 123.买卖股票的最佳时机III 188.买卖股票的最佳时机IV

123. 买卖股票的最佳时机 III 给定一个数组&#xff0c;它的第 i 个元素是一支给定的股票在第 i 天的价格。 设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。 注意&#xff1a;你不能同时参与多笔交易&#xff08;你必须在再次购买前出售掉之前的股票&a…

安全开发实战(2)---域名反查IP

目录 安全开发专栏 前言 域名与ip的关系 域名反查ip的作用 1.2.1 One 1.2.2 Two 1.2.3 批量监测 ​总结 安全开发专栏 安全开发实战http://t.csdnimg.cn/25N7H 这步是比较关键的一步,一般进行cdn监测后,获取到真实ip地址后,或是域名时,然后进行域名反查IP地址,进行进…

基于Springboot的职称评审管理系统

基于SpringbootVue的职称评审管理系统的设计与实现 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatis工具&#xff1a;IDEA、Maven、Navicat 系统展示 用户登录 首页 评审条件 论坛信息 系统公告 后台登录页面 用户管理 评审员管理 省份…

再谈C语言——理解指针(四)

assert断⾔ assert.h 头⽂件定义了宏 assert() &#xff0c;⽤于在运⾏时确保程序符合指定条件&#xff0c;如果不符合&#xff0c;就报错终⽌运⾏。这个宏常常被称为“断⾔”。 assert(p ! NULL); 上⾯代码在程序运⾏到这⼀⾏语句时&#xff0c;验证变量 p 是否等于 NULL 。…

​LeetCode解法汇总2385. 感染二叉树需要的总时间

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 给你一棵二叉树的根节点 root &#xff0…

创建型设计模式

七大原则 1. 开闭原则&#xff08;Open-Closed Principle, OCP&#xff09; 详解&#xff1a;软件实体&#xff08;类、模块、函数等&#xff09;应该易于扩展&#xff0c;但是不易于修改。换句话说&#xff0c;当软件需求变化时&#xff0c;应该通过添加新代码来实现变化&am…

销冠必备:高效跟进客户的四个技巧

作为一名销售&#xff0c;高效而精准地跟进客户是取得成功的关键。今天&#xff0c;我将分享四个技巧&#xff0c;让你也能够高效的跟进客户。 1、善于发问 通过多询问客户&#xff0c;你可以更好地了解客户的需求和痛点。在与客户交流时&#xff0c;不要只是简单地回答问题&…

业务复习知识点Oracle查询

业务数据查询-1 单表查询 数据准备 自来水收费系统建表语句.sql 简单条件查询 精确查询 需求 &#xff1a;查询水表编号为 30408 的业主记录 查询语句 &#xff1a; select * from t_owners where watermeter 30408; 查询结果 &#xff1a; 模糊查询 需求 &#xff1a;查询业…

毕业设计注意事项(2024届更新中)

1.开题 根据学院发的开题报告模板完成&#xff0c;其中大纲部分可参考资料 2.毕设 根据资料中的毕设评价标准&#xff0c;对照工作量 3.论文 3.1 格式问题 非常重要&#xff0c;认真对比资料中我发的模板&#xff0c;格式有问题&#xff0c;答辩输一半&#xff01; 以word…

W801学习笔记十四:掌机系统——菜单——尝试打造自己的UI

未来将会有诸多应用&#xff0c;这些应用将通过菜单进行有序组织和管理。因此&#xff0c;我们需要率先打造好菜单。 LCD 驱动通常是直接写屏的&#xff0c;虽然速度较快&#xff0c;但用于界面制作则不太适宜。所以&#xff0c;最好能拥有一套 UI 框架。如前所述&#xff0c;…

【linux】编译器使用

目录 1. gcc &#xff0c;g 编译器使用 a. 有关gcc的指令&#xff08;g同理&#xff09; 2. .o 文件和库的链接方式 a. 链接方式 b. 动态库 和 静态库 优缺点对比 c. debug 版本 和 release 版本 1. gcc &#xff0c;g 编译器使用 a. 有关gcc的指令&#xff08;g同理&…

设计模式-创建型-抽象工厂模式-Abstract Factory

UML类图 工厂接口类 public interface ProductFactory {Phone phoneProduct();//生产手机Router routerProduct();//生产路由器 } 小米工厂实现类 public class XiaomiFactoryImpl implements ProductFactory {Overridepublic Phone phoneProduct() {return new XiaomiPhone…

Node.js -- fs模块

文章目录 1. 写入文件1.1 写入文件1.2 同步和异步1.3 文件追加写入1.4 流式写入1.5 文件写入的场景 2. 读取文件2.1 异步和同步读取2.2 读取文件应用场景2.3 流式读取2.4 fs 练习 -- 文件复制 3. 文件重命名和移动4. 文件删除5. 文件夹操作5.1 创建文件夹5.2 读取文件夹5.3 删除…

crossover和wine哪个好 wine和crossover有什么本质区别 苹果电脑运行Windows crossover24

CrossOver是Wine的延伸产品&#xff0c;CrossOver可以简单的理解为类虚拟机&#xff0c;那么wine是什么&#xff0c;许多小伙伴就可能有些一知半解。CrossOver和wine哪个好&#xff0c;wine和CrossOver有什么本质区别呢&#xff1f;下文将围绕着这两个问题展开。 一、CrossOve…