Python——函数

概念

函数是一段具有特定功能,可重复使用的代码,python提供了很多内置函数,如:print(),input(),len()函数等,以及标准库函数,math库中的sqrt()函数等,除此之外用户还可以自己定义函数,称为自定义函数。

函数的定义

def 函数名 ([形式参数列表]):
    函数体
    [return 返回值]
  • 其中def是Python的关键字,用于定义函数

  • 形式参数列表(简称形参)是调用该函数时传递给函数的参数,可以是零个或多个,当传递的多个参数时各参数之间用逗号隔开,[]表示可选的内容

  • 函数体是每次调用函数执行的代码,由一行或多行语句组成。

  • 定义函数时须注意:

  • 当函数参数为零个时,也必须保留一对空的圆括号

  • 圆括号后面的冒号不可省略

  • 函数体对于def关键字必须保持一定的空格缩进

函数的调用

函数定义后,须调用函数才能执行函数体,实现特定功能。

函数名 ([实际参数列表])

实际参数列表(简称实参)表示要传递给函数的具体值

当我们定义好函数后执行,会发现什么都没有,这是就是因为没有调用函数的原因,定义函数可以理解为只是找好了员工还没有工作

调用函数时,会将函数内的语句一并执行,不要再加print输出

函数的传参

传入参数的功能是:在函数进行计算的时候,接受外部(调用时)提供的数据

定义函数时,圆括号内的参数为形参,表名函数声明要使用的参数,多个参数用逗号隔开

调用函数时,圆括号内的参数为实参,表示函数执行时真正使用的参数值,多个参数用逗号隔开

在Python中,函数参数的数据类型可分为不可变数据类型(如整数,浮点数,字符串,元组等)和可变数据类型(列表,字典,集合等)当参数为不可变数据类型时,在函数内部直接修改不会影响实参

但当参数的数据类型为可变数据类型时,在函数内使用下标或其他方式增删改元素,实参也会更改

参数类型

位置参数

位置参数,有时也称必备参数,调用函数时传入实际参数的数量和位置都必须和定义函数时保持一致

可以看到这里因为第三个调用函数时传递的实参数量与形参不符,触发了类型错误:

add()缺少一个必需的位置参数:‘y’

同样,多参数也会触发报错:add()需要两个位置参数,但是提供了三个

默认值参数

在定义函数时,可以为函数的参数设置默认值,此参数成为默认值参数,在调用带默认值的函数时,可以不用为默认值参数传值,此时函数将会直接使用定义时的默认值,也可以通过显式赋值来替换掉默认值

可以看到设定默认值之后即使传入实参与形参数量不符也不会报错

还可以使用函数名.__defaults__查看函数当前设定的所有默认值,返回值的类型是一个元组,其中的元素依次表示当前设定的每个默认值

如果形参的默认值是一个变量,那么形参的默认值只取决于函数定义时该变量的值(也就是指定默认值变量在函数定义之前最接近函数的值)如果函数后或者函数中重新给变量赋值不会更改默认值参数

关键字参数

关键字参数是指调用函数时按形参名传递值。使用关键字参数允许函数调用时参数的顺序与定义时的不一样,python解释器能够使用参数名匹配参数值

不定长参数

通常在定义一个参数时,若希望函数能够处理比定义时更多的参数,此时可在函数中使用‘*’或‘**’符号标识不定长参数

  • *:表示接受任意多个参数,并将其存放在一个元组中

  • **:表示接受任意多个参数,并将其存放在字典中,实参格式类似关键字参数

调用greet函数,传入多个值,这些值会自左往右依次匹配形参,首先将 ‘hi!’传递给say,接着将‘小兰,小五,小红’组成一个元组传递给names,最后将“小李 = ‘你好’,小明 = ‘hello!’”转换为字典传递给name_say

函数的返回值

函数除了可以在函数体中直接输出数据,还可以返回一个或多个值,称为函数的返回值return

return用于退出函数并将程序结果返回到函数调用位置继续执行,同时返回零个或多个值

拥有return语句就要使用print函数打印返回值,如果没有return语句,默认将以return None结束即返回空值

None作为一个特殊的字面量,用于表示空。无意义,其有非常多的应用场景

  • 用在函数无返回值上

  • 用在if判断

  • 在if判断中None等同于False

  • 一般用于在函数中主动返回None,配合if判断做相关处理

因为None本身就代表着false,所以进行判断就可以得到我们想要的结果

才试了一下,原来直接if re也可以表示如果re为真,只是跟if not的意思反了过来

  • 用于声明无内容的变量上

  • 定义变量,但暂时不需要变量有具体值,可以使用None来代替

可以看到打印出来的也是None,a的数据类型是NoneType

返回值也可以有多个,元素之间用逗号隔开。函数调用后多个返回值将以元组的形式保存

函数的嵌套

函数的嵌套定义就是在函数内又定义了另一个函数

函数的嵌套调用就是在函数中调用另外一个函数

例:

在函数内嵌套定义函数,在函数内嵌套调用函数

需要注意的是,这里的fun_b函数只在丁一开始到fun_a函数结束范围内有效

在外部嵌套调用函数,调用fun_b先输出2,再调用fun_a打印1,最后输出3

函数的递归

函数的递归是一种嵌套调用的特殊形式,即函数直接或间接的调用其本身,套娃

直接递归调用就是在函数总调用函数本身

可以看到在fun函数中调用了fun函数,导致一直输出1,直到重复太多次被编译器报错警告

间接递归调用时在fun函数中调用fun1函数,而fun1函数又调用了fun函数

但如果只能这样也就是个无线死循环,没有实际意义,因此所有递归函数都需要设定终止条件

利用递归求阶乘

数学上阶乘通常定义为:

n! = n(n-1)(n-2)...(1)

虽然之后几行,但是讲起来有点小复杂

首先先输入要求阶乘的整数,我这里是5,然后调用fact函数,进入到函数体判断是否为0,如果为0就返回1(也充当着结束条件的作用)

因为传入的参数是5所以进入else(这里定义一个y接受数据,主要是方便在调试中查看数据变化),执行n * fact(n - 1),因为这里又调用了fact函数并且传入了参数n-1,所以有重新进入到fact函数中,直到最后n = 1然后传入 n-1等于0时函数return 1,结束递归调用

结束以后,y的值就要一层一层的进行运算了,首先是因为结束时fact函数的返回值为1,所以传递到fact(n-1)就等于1,本来n也等于1,所以就是1 * 1,y = 1,暂用f(1)代替,那么继续执行return将f(1)的值传递给上层f(2),这时n等于2 ,所以f(2)就等于2 * f(1) = 2 * 1 = 2,依次类推

f(3):n = 3,f(3) = 3 * f(2) = 3 * 2 = 6

f(4):n = 4,f(4) = 4 * f(3) = 4 * 6 = 24

f(5):n = 5,f(5) = 5 * f(4) = 5 * 24 = 120

最后得出的结果打印出来就是5的阶乘,文字可能有点难理解,这里画了一个草图,更加直观

斐波那契数列

利用函数的递归计算斐波那契数列的第n项,斐波那契数列从第三项开始,元素值为前两个元素的和,如:1,1,2,3,5,8,13,21,34,55

首先定义的当n = 1和 n = 2时都返回1,也就是给函数递归调用的终止条件,当n等于5时,根据课本也画了一个草图,很直观就能知道斐波那契数列的执行步骤,递归终止后,就会利用返回值向上进行计算,得到最终值

变量的作用域

当一个程序中包含多个函数时,可在各函数中分别定义变量,所以变量的作用域指的是变量的作用范围( 变量在哪里可用,在哪里不可用)

主要分两类:局部变量和去全局变量

局部变量

局部变量是定义在函数体内部的变量,只能在变量定义开始到函数结束的范围内使用,它与函数外具有相同名称的变量没有任何关系,此外函数的形参也属于局部变量,作用范围仅限于函数内部

可以看到当我们调用函数的时候可以直接输出num变量的值

但是当我们在函数外再次打印num的值是就会触发报错,说num没有被定义,这就是局部变量,当num变量执行到函数结束时就被销毁了

全局变量

所谓全局变量,指的是在函数体内、外都能生效的变量

如果有一个数据,在函数A和函数中都要使用,该怎么办?

只需要将这个数据设定为全局变量就好了

这就是在函数外定义的全局变量,对变量定义之下的整个程序都生效,两个函数都没有定义num变量的值,可以直接访问全局变量获取

global关键字

global关键字可以在函数内部声明变量为全局变量

使用global关键字可以分为以下两种情况

  • 变量已在函数外创建,如果需要在函数内使用或修改该变量,需要在函数内使用关键字global声明该全局变量

  • 变量没有在函数外创建,在函数内直接使用global关键字声明全局变量,然后赋值,调用该函数后,会创建新的全局变量,在函数外也可以使用或修改该变量

可以看到当我们不使用global关键字时,test_a中的num = 250,相当于test_a又在函数内声明了一个局部变量,跟外部的全局变量num没有任何关系,不会改变函数外num的值

当我们使用了global关键字声明num就会发现,global关键字会将在函数内定义的变量成为全局变量,当调用test_a函数时,函数外定义的变量也会发生改变

nonlocal关键字

如果要在一个嵌套函数中使用或修改嵌套外部作用域中的变量,须使用nonlocal关键字修饰该变量

可以看到当我们在内层函数inner中修改变量num并不会更改外层函数outer的值,只会在函数内部生效

一开始在外层outer函数中num = 1 当我们想要更改变量时,只需要在内层函数inner内部使用nonlocal函数声明num可以实现对外层函数变量的改变

nonlocal关键字与global关键字的区别

这两个关键字拿出来我一开始也是蒙的,不知道有啥区别

为了实践,我又定义了一个iner函数跟inner函数并列,应该可以说是outer函数的子函数

当我们在inner函数中利用nonlocal关键字声明的时候,发现iner函数并没有享受到nonlocal关键字的变量声明,由此可得不管iner函数属于inner还是与其并列,nonlocal关键字作用于外部内嵌函数的变量,不会对声明变量以下的函数生效

以下两张截图都是在最下层的iner函数中利用nonlocal关键字声明变量,可以看到在其上的函数,如果没有在内部给变量num赋值时,也会享受到nonlocal关键字的变量声明

如果产生了对同意变量的赋值,也就是相当于在函数中又定义了一个局部变量,所以不管iner函数是属于inner函数还是与其并列,都不会改变inner函数中定义的num变量值

还有就是,如果在函数内定义的变量再使用nonlocal关键字修改,不会产生新的全局变量,当我们在函数外打印变量时会报错说变量num没有被定义

global关键字虽然不能够作用于嵌套函数,但是global关键字可以改变全局变量,同时可以定义新的全局变量;nonlocal关键字只能改变外层函数变量不能定义新的外层函数变量,并且nonlocal也不能改变全局变量。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Hive3面试基础

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、基本知识Hive31.表的类型和表的存储格式a)b)c)创建表i)ii) 2.表 二、使用步骤1.引入库2.读入数据 总结 前言 面试准备之Hive 回顾…

设计模式之适配器模式

目录 1、什么是适配器模式 2、为什么用适配器模式 3、适配器模式的结构 4、类适配器模式代码实现 4.1 思想 4.2 代码实现 4.3 问题分析 5、对象适配器模式代码实现 5.1 思想 5.2 代码实现 6、适配器模式应用场景 1、什么是适配器模式 适配器模式(Adapter…

19. Unity - 2D游戏开发小记02 --- 伪透视图、2D物体碰撞、瓦片地图碰撞、素材缩放平铺

1. 伪视图 在2D游戏开发当中,当角色移动时,会发生物体与物体之间的前后遮挡。2D视图中的前后关系是由 Y 轴决定,y 值越小物体越靠前。unity的渲染应开启根据 y 值的大小进行渲染才能保证正确的遮挡效果,在菜单栏Editor–>project setting --> Graphic中按照下图方式…

C++三大特性—继承“复杂的菱形继承及菱形虚拟继承”

C的一个大坑:菱形继承 希望这篇文章能让你理解什么是菱形继承,以及菱形继承的注意事项 单继承与多继承 单继承:一个子类只有一个直接父类时称这个继承关系为单继承 多继承:一个子类有两个或以上直接父类时称这个继承关系为多继承…

凌恩生物美文分享|HGTree v2.0:水平基因转移数据库

水平基因转移(HGT)是指遗传物在物种间从一个相邻生物体到另一个生物体横向传递,是原核生物遗传变异的重要过程。HGT是负责塑造原核生物基因组和在自然选择中生存的驱动力之一,对原核生物的进化有很大贡献,但它会使物种进化史复杂化&#xff0…

【Linux】进程信号保存

前言 上篇博客我们了解了进程信号的概念和信号如何产生。 本篇我们将学习进程信号如何保存。 文章目录 前言一. 阻塞信号二. 递达动作三. 信号集四. 信号集操作函数结束语 一. 阻塞信号 首先我们需要一些预备知识 实际执行信号的处理动作称为信号递达(Delivery&am…

数字图像处理-绪论

数字图像处理-绪论 文章目录 前言一、闲谈二、什么是数字图像处理?2.1. 什么是数字图像?2.1.1. 可见光图像2.1.2. 不可见光图像 2.2. 什么是数字图像处理? 三、数字图像处理的前世今生3.1. 数字图像处理的前世3.2. 数字图像处理的今生 四、数…

【嵌入式系统】课程复习资料整理

【嵌入式系统】课程复习资料整理 一、绪论 1.定义 从技术的角度定义:以应用为中心、以计算机技术为基础、软件硬件可裁剪、对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。从系统的角度定义:嵌入式系统是设计完成复杂功能的硬件和软件&a…

使用crontab定时自动更新DDNS

需求说明: N1盒子的armbian系统配置好了 ipv6 的ddns,实现了域名访问本机,但是本地ipv6可能会发生变化,当发生变化后,需要手动执行指令,将新的ip与域名绑定,现在我们采用定时任务,每…

Nuvoton NK-980IOT开发板 u-boot 编译

前言 最近搭建了 Nuvoton NK-980IOT开发板 的开发编译环境,记录一下 u-boot 的 编译流程 Nuvoton NK-980IOT开发板 资源还是比较的丰富的,可以用于 嵌入式Linux 或者 RT-Thread 的学习开发 开发板上电比较的容易,两根 USB 线即可&#xff0…

计网笔记 01 概述 计算机网络体系结构、参考模型

文章目录 前言1、计网概述1.1 概念、组成、功能、分类1.1.1 概念1.1.2 计网组成1.1.2 计网分类 1.2 标准化工作及相关组织1.2.1 标准的分类 1.3 性能指标★★★1.3.1 速率相关性能指标1.3.2 时延相关指标 2、体系结构&参考模型★★★★★(对应王道视频7-10p 相当…

Android Jetpack:利用Palette进行图片取色

与产品MM那些事 新来一个产品MM,因为比较平,我们就叫她A妹吧。A妹来第一天就指出:页面顶部的Banner广告位的背景是白色的,太单调啦,人家不喜欢啦,需要根据广告图片的内容自动切换背景颜色,颜色…

基于CUDA的GPU计算PI值

访问【WRITE-BUG数字空间】_[内附完整源码和文档] 基于CUDA的GPU计算PI值。本项目使用CUDA编程模型并行计算PI值,研究GPU与CPU效率的比较,分析不同GPU线程分块对性能的影响。 异构计算试验报告 —实验1:基于CUDA的GPU计算PI值 第一部分&…

JS逆向 -- 某平台登录加密分析

一、打开网站,使用账号密码登录 账号:aiyou123.com 密码:123456 二、通过F12抓包,抓到如下数据,发现密码加密了 三、加密结果是32位,首先考虑是md5加密。 四、全局搜索pwd,点击右上角&#xf…

【ros2】ros melodic迁移到ros2 dashing过程中碰到的问题及解决方法

序言 总结踩坑经历,以利他人 1. error: forming pointer to reference type … & 报错原因: ros2回调函数的参数不能是引用形式 &,需要去除& 解决方法: 如果是指针引用,直接去除引用 void Callback(con…

javascript中的严格模式

认识严格模式: 在ECMAScript5标准中,JavaScript提出了严格模式的概念(Strict Mode): 严格模式很好理解,是一种具有限制性的JavaScript模式,从而是代码隐式的脱离了“懒散(sloppy)模…

软件测试实战,Web测试详细总结 (覆盖所有测试点),你要的都有

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 Web自动化测试&…

在技术圈超卷的当下,学历到底是敲门砖还是枷锁?

前言 最近,突然之间被“孔乙己文学”刷屏了,短时间内“孔乙己文学”迅速走红,孔乙己是中国文学中的一位经典人物,他的长衫被认为是他的象征之一,孔乙己的长衫折射出很多现象,既有社会的,也有教育…

Android平台播放透明视频

Android平台播放透明视频 思路 设计一种特殊的视频,它的一半内容存储alpha信息,另一半内容存储rgb信息,接着通过OpenGL获取每个像素点的alpha值和rgb值进行混合,最后出来的画面就是带有透明效果的视频了。 可以上下的分&#xf…

服务器中了勒索病毒,升级后的Malox勒索病毒特征,勒索病毒解密数据恢复

Mallox勒索病毒是网络上较为流行的勒索病毒,但是随着黑客加密技术的不断升级,Mallox勒索病毒的新升级版本Malox勒索病毒已经开始出现。Malox勒索病毒是一种最近在网络上广泛传播的恶意软件,其感染方式多种多样,主要以加密受害人的…