Python从0到100(十五):函数的高级应用

news2024/12/29 8:38:33

在这里插入图片描述

前言: 零基础学Python:Python从0到100最新最全教程。 想做这件事情很久了,这次我更新了自己所写过的所有博客,汇集成了Python从0到100,共一百节课,帮助大家一个月时间里从零基础到学习Python基础语法、Python爬虫、Web开发、 计算机视觉、机器学习、神经网络以及人工智能相关知识,成为学习学习和学业的先行者!
欢迎大家订阅专栏:零基础学Python:Python从0到100最新最全教程!

一、 闭包

闭包定义:
Python函数是支持嵌套的。 如果在一个内部函数中对外部函数作用域(非全局作用域)的变量进行引用,那么内部函数就会被称为闭包。闭包需要满足如下3个条件:

  • 存在于两个嵌套关系的函数中,并且闭包是内部函数;
  • 内部函数引用了外部函数的变量(自由变量);
  • 外部函数会把内部函数的函数名称返回。

闭包示例:
在这里插入图片描述

二、装饰器

1.装饰器的概念

假设我们已经开发了一个本有的函数,后续可能会增加临时的需求,例如插入日志,我们可以增加一个包裹函数,由它来负责这些额外的需求,这个包裹函数就是 装饰器
装饰器主要应用在如下场景:

  1. 引入日志;
  2. 函数执行时间统计;
  3. 执行函数前预备处理;
  4. 执行函数后清理功能;
  5. 权限校验;
  6. 缓存。

装饰器是一个函数,它需要接收一个参数,该参数表示被修饰的函数。例如,有如下一个装饰器函数:

def myDectoration(func):
    def inner():
        print("正在执行内部函数")
        func()
    return inner

def printMessage():
    print("--------欢迎您-------")
pm = myDectoration(printMessage)
pm()
# 正在执行内部函数
# --------欢迎您-------
  • 装饰器是个嵌套函数
  • 内部函数是一个闭包。
  • 外部函数接收的是被修饰的 函数(func)

通过在函数定义的前面添加@符号和装饰器名,实现装饰器对函数的包装。给f1函数加上装饰器,示例如下:

@w1
def f1():
    print(’f1')

此时,程序会自动编译生成调用装饰器函数的代码,等价于:

f1 = w1(f1)

2. 多个装饰器

多个装饰器应用在一个函数上,调用顺序是从下至上

@w1
@w2
def f1():
    print(---f1---)

执行顺序:
先执行@w2,后执行@w1

3.装饰有参数的函数

看看下面的代码,运行结果是什么呢?

def w1(func):
	def inner(a,b):
		print('开始验证权限')
		func(a,b)
	return inner
@w1
def tes(a,b):
    print('a=%d,b=%d'%(a,b))
tes(1,2)
# 开始验证权限
# a=1,b=2

三、递归调用

Python中允许函数嵌套定义,也允许函数之间相互调用,而且一个函数还可以直接或间接的调用自身。

def fac(num):
    if num in (0, 1):
        return 1
    return num * fac(num - 1)

上面的代码中,fac函数中又调用了fac函数,这就是所谓的递归调用。代码第2行的if条件叫做递归的收敛条件,简单的说就是什么时候要结束函数的递归调用,在计算阶乘时,如果计算到01的阶乘,就停止递归调用,直接返回1;代码第4行的num * fac(num - 1)是递归公式,也就是阶乘的递归定义。下面,我们简单的分析下,如果用fac(5)计算5的阶乘,整个过程会是怎样的。

# 递归调用函数入栈
# 5 * fac(4)
# 5 * (4 * fac(3))
# 5 * (4 * (3 * fac(2)))
# 5 * (4 * (3 * (2 * fac(1))))
# 停止递归函数出栈
# 5 * (4 * (3 * (2 * 1)))
# 5 * (4 * (3 * 2))
# 5 * (4 * 6)
# 5 * 24
# 120
print(fac(5))    # 120

注意,函数调用会通过内存中称为“栈”(stack)的数据结构来保存当前代码的执行现场,函数调用结束后会通过这个栈结构恢复之前的执行现场。栈是一种先进后出的数据结构,这也就意味着最早入栈的函数最后才会返回,而最后入栈的函数会最先返回。例如调用一个名为a的函数,函数a的执行体中又调用了函数b,函数b的执行体中又调用了函数c,那么最先入栈的函数是a,最先出栈的函数是c。每进入一个函数调用,栈就会增加一层栈帧(stack frame),栈帧就是我们刚才提到的保存当前代码执行现场的结构;每当函数调用结束后,栈就会减少一层栈帧。通常,内存中的栈空间很小,因此递归调用的次数如果太多,会导致栈溢出(stack overflow),所以递归调用一定要确保能够快速收敛。我们可以尝试执行fac(5000),看看是不是会提示RecursionError错误,错误消息为:maximum recursion depth exceeded in comparison(超出最大递归深度),其实就是发生了栈溢出。

我们使用的Python官方解释器,默认将函数调用的栈结构最大深度设置为1000层。如果超出这个深度,就会发生上面说的RecursionError。当然,我们可以使用sys模块的setrecursionlimit函数来改变递归调用的最大深度,例如:sys.setrecursionlimit(10000),这样就可以让上面的fac(5000)顺利执行出结果,但是我们不建议这样做,因为让递归快速收敛才是我们应该做的事情,否则就应该考虑使用循环递推而不是递归。

再举一个之前讲过的生成斐波那契数列的例子,因为斐波那契数列前两个数都是1,从第3个数开始,每个数是前两个数相加的和,可以记为f(n) = f(n - 1) + f(n - 2),很显然这又是一个递归的定义,所以我们可以用下面的递归调用函数来计算第​n个斐波那契数。

def fib(n):
    if n in (1, 2):
        return 1
    return fib(n - 1) + fib(n - 2)


# 打印前20个斐波那契数
for i in range(1, 21):
    print(fib(i))

需要提醒大家,上面计算斐波那契数的代码虽然看起来非常简单明了,但执行性能是比较糟糕的,原因大家可以自己思考一下,更好的做法还是之前讲过的使用循环递推的方式,代码如下所示。

def fib(n):
    a, b = 0, 1
    for _ in range(n):
        a, b = b, a + b
    return a

四、常见Python内置函数

1.map函数

map函数会根据提供的函数对指定的序列做 映射
map函数的定义如下:

map(function, iterable,)

第1个参数是函数的名称;第2个参数表示支持迭代的容器或者迭代器
map函数的作用是以参数序列中的每个元素分别调用function函数,把每次调用后返回的结果保存为对象。

func = lambda x:x+2
result = map(func, [1,2,3,4,5])
print(list(result))

2.filter函数

filter函数会对指定序列执行 过滤操作
filter函数的定义如下:

filter(function,iterable)

第1个参数可以是函数的名称;第2个参数表示的是序列、支持迭代的容器或迭代器。

func = lambda x:x%2
result = filter(func, [1, 2, 3, 4, 5])
print(list(result))

装饰器是Python中的特色语法,可以通过装饰器来增强现有的函数,这是一种非常有用的编程技巧。一些复杂的问题用函数递归调用的方式写起来真的很简单,但是函数的递归调用一定要注意收敛条件和递归公式,找到递归公式才有机会使用递归调用,而收敛条件确定了递归什么时候停下来。

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

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

相关文章

地图图源#ESRI ArcGIS XYZ Tiles系列(TMS)

目录 1、前言 2、地图图源网址 2.1、Satellite 卫星图源 2.2、Terrain 地形图源 2.3、Street 路网/标注图源 2.4、Specifity 特色设计图源 3、专业推荐”穿搭“ 4、图源配置下载及使用 图源名称图层类别特别注意谷歌 Google①地形 ②影像 ③矢量及标注 ④特色图源国内大…

迭代加深搜索(图的路径查找)

目录 概念 优点 缺点 如何剪枝(八数码) 剪枝策略: 深度优先搜索(DFS)和广度优先搜索(BFS) 深度优先搜索(DFS) 广度优先搜索(BFS) 比较 应…

Facebook账号运营要用什么IP?

众所周知,Facebook封号大多数情况都是因为IP的原因。Facebook对于用户账号有严格的IP要求和限制,以维护平台的稳定性和安全性。在这种背景下,海外IP代理成为了一种有效的解决方案,帮助用户避免检测,更加快捷安全地进行…

基于51单片机的电子秤LCD1602液晶显示( proteus仿真+程序+设计报告+讲解视频)

基于51单片机电子秤LCD显示 1. 主要功能:2. 讲解视频:3. 仿真设计4. 程序代码5. 设计报告6. 设计资料内容清单&&下载链接 基于51单片机电子秤LCD显示( proteus仿真程序设计报告讲解视频) 仿真图proteus8.9及以上 程序编译器&#xf…

OceanBase开发者大会2023届视频及PPT汇总

数据库技术趋势 我眼中的数据库技术 阳振坤OceanBase 首席科学家 观看视频 下载 PDF 未来,中国需要什么样的数据库? 周傲英华东师范大学副校长,CCF 会士 观看视频 下载 PDF 云原生技术趋势解读 Keith ChanCNCF 云原生计算基金会中国区总监 …

Linux嵌入式驱动开发-阻塞IO与非阻塞IO

文章目录 阻塞与非阻塞访问简介阻塞访问的实现等待队列等待队列头等待队列项从等待队列头添加/移除等待队列项等待唤醒等待事件API 非阻塞访问的实现轮询poll 函数原型可以返回的资源状态 阻塞与非阻塞访问简介 **IO:**Input/Output,也就是输入/输出&am…

【无标题】vscode 配置c++ c编译环境

不用图形化也可以直接把launcher.json c_c_properties.json task.json复制到项目里 首先打开 vscode创建项目 ctrlshiftp 打开c/c edit configuration UI 配置生成c_cpp_properties.json文件 这里选择gcc为 c运行环境 只需要改配置名称跟编译器路径两处其他默认 选g为c环境 可…

Docker容器化部署(企业版)

大家好,webfunny前端监控埋点系统,已经正式发布了webfunny的官方镜像: Webfunny镜像目录:https://hub.docker.com/r/webfunny/webfunny_monitor_cluster/tags 部署前提是你的服务器已经安装了Docker环境,没有安装doc…

pygame 烟花效果

# 初始化 pygame.init() screen_width 800 screen_height 600 screen pygame.display.set_mode((screen_width, screen_height)) pygame.display.set_caption(烟花效果) # 焰火发射 particles [] # 焰火粒子 def firework(x, y): num_particles 100 # 每次发射的…

Springboot+Vue项目-基于Java+MySQL的影城管理系统(附源码+演示视频+LW)

大家好!我是程序猿老A,感谢您阅读本文,欢迎一键三连哦。 💞当前专栏:Java毕业设计 精彩专栏推荐👇🏻👇🏻👇🏻 🎀 Python毕业设计 &…

【Python-面向对象】

Python-面向对象 ■ 事物和类■ 成员方法定义和使用■ self■ 构造方法__init__()■ 魔术方法■ __str__字符串方法■ __lt__小于、大于符号比较■ __le__小于等于、大于等于符号比较■ __eq__符号比较■ 综合演示 ■ 封装■ 私有成员和方法 ■ 继承■ 单…

STM32之HAL开发——ILI9341液晶控制器

ILI9341液晶控制器简介 本液晶屏内部包含有一个液晶控制芯片ILI9341,它的内部结构非常复杂,如下图。该芯片最主核心部分是位于中间的GRAM(Graphics RAM),它就是显存。GRAM中每个存储单元都对应着液晶面板的一个像素点。它 右侧的各种模块共同…

Ubuntu20.04 ISAAC SIM仿真下载使用流程

机器:华硕天选X2024 显卡:4060Ti ubuntu20.04 安装显卡驱动版本:525.85.05 参考: What Is Isaac Sim? — Omniverse IsaacSim latest documentationIsaac sim Cache 2023.2.3 did not work_isaac cache stopped-CSDN博客 Is…

聚观早报 | TCL召开电视新品发布会;OceanBase 4.3发布

聚观早报每日整理最值得关注的行业重点事件,帮助大家及时了解最新行业动态,每日读报,就读聚观365资讯简报。 整理丨Cutie 4月22日消息 TCL召开电视新品发布会 OceanBase 4.3发布 科大讯飞推出耳背式助听器 F1联想中国大奖赛开赛 蔚来展…

力扣——并查集算法系列

【LeetCode 684. 冗余连接】 思路: 首先因为这是一个无向图,所以不需要考虑谁是树根。 那么我们一条条边加入到图里去,直到出现了环为止,那么这条边就是冲突的边,需要删除掉。 那么怎么判断是否出现了环呢&#xff…

36. 【Android教程】侧滑菜单:DrawerLayout

侧滑菜单是用来在页面上增加一个抽屉式菜单栏的控件,它一般位于左侧,用户可以通过侧滑拉出或者关闭。通常你可以放置一些菜单项或者上下文相关的设置在里面,帮助你节省屏幕空间同时可以很方便的随时打开。侧滑菜单其实就是下面这货&#xff1…

python 对图片进行操作

Pillow是一个强大的图像处理库,它提供了许多用于打开、操作和保存图像的功能。 Image模块: Image模块提供了用于打开、创建、编辑和保存图像的基本功能。可以使用Image.open()函数来打开图像文件,或者使用Image.new()函数来创建新的图像,还可…

【Java框架】Spring框架(六)——Spring中的Bean的作用域

目录 Bean的作用域1.singleton(默认)代码示例 2.prototype代码示例 3.request代码示例 4.session代码示例 5.application代码示例 websocket Bean的作用域 Spring支持6个作用域:singleton、prototype、request、session、application、websocket 1.singleton(默认…

山与路远程控制 一个基于electron和golang实现的远控软件

山与路远程控制 🎥项目演示地址 还在制作… ♻️项目基本介绍 山与路远程控制是基于electron(vue3)和golang实现的远程控制软件(项目界面主要模仿向日葵远程软件,如有侵权请告知),代码可能有点臃肿毕竟只花了一周左右写的无聊项目,如果对其感兴趣的大佬可以fork自…

【信号处理】心电信号传统R波检测定位典型方法实现(matlab)

关于 心电信号中QRS波检测是一个非常重要的步骤,可以用于实现重要波群的基本定位,在定位基础上,可以进一步分析心电信号的特征变化,从而为医疗诊断提供必要的参考。 工具 MATLAB ECG心电信号 方法实现 ECG心电信号加载 ecg …