前言

对于上节课的 递归函数 ,很多同学在后台私信我,说递归函数这块是没有看明白是什么意思的,那么我在这里给你们举例说明一下递归函数的原理吧!

大致的递归的原理就是这样的,是有点复杂的,但是也不太难,如果还是没有看明白的同学,建议先跳过这个,因为这个在现在的阶段,了解一下就可以了,不必太深入这个。好的,那么就开始我们今天的课程吧!

什么是函数的参数

在定义python函数时可定义形参(形式参数的意思),这些形参的值要等到调用时才能确定下来,由函数的调用者负责为形参传入参数值,简单来说,就是谁调用函数,谁负责传入参数值。

关键字(keyword)参数

python函数的参数名不是无意义的,python允许在调用函数时通过名字来传入参数值,因此,python函数的参数名应该具有更好的语义----程序可以立刻明确传入函数的每个参数的含义。
按照形参位置传入的参数被称为位置参数。如果使用位置参数的方式来传入参数值,则必须严格按照定义函数时指定的顺序来传入参数值;如果根据参数名来传入参数值,则无须遵守定义形参的顺序,这种方式被称为关键字(keyword)参数,例:

def girth(width, height):print("width:", width)print("height:", height)return 2 * (width + height)#传统调用函数的方式,根据位置传入参数值
print(girth(3.2, 4.8))
#根据关键字参数来传入参数值
print(girth(width = 3.2, height = 4.8))
#在使用关键字参数时可交换位置
print(girth(height = 4.8, width=3.2))
#部分使用关键字参数,部分使用位置参数
print(girth(3.5, height = 4.8))输出结果:
width: 3.2
height: 4.8
16.0

上面程序定义了一个简单的girth()函数,该函数包含 width、height两个参数,该函数与前面定义的函数并没有任何区别。

接下来在调用函数时,既可使用传统的根据位置参数来调用(如:girth(3.2, 4.8)),也可根据关键字参数来调用(如:girth(width = 3.2, height = 4.8)),在使用关键字参数调用时可交换参数的位置(如:girth(height = 4.8, width=3.2)),还可混合使用位置参数和关键字参数(如:girth(3.5, height = 4.8))

需要说明的是,如果希望在调用函数时混合使用关键字参数和位置参数,则关键字参数必须位于位置参数之后,换句话说,在关键字参数之后的只能是关键字参数,例如如下代码是错误的:

print(girth(width = 3.5, 4.8))输出结果:
SyntaxError:positional argument follows keyword argument

参数默认值

在某些情况下,程序需要在定义函数时为一个或多个形参指定默认值-----这样在调用函数时就可以省略为该形参传入参数值,而是直接使用该形参的默认值。
语法格式如下:

def 函数名 (形参名 = 默认值) :

从上面的语法格式可以看出,形参的默认值紧跟在形参之后,中间以英文 “=” 隔开。例:

def say_hi (name = "virus", message = "欢迎你学习python"):print(name, ",", "你好")print("消息是:", message)say_hi()
say_hi("baba")
say_hi("baba","恭喜你通过python等级考试")输出结果:
直接使用默认参数:
virus , 你好
消息是: 欢迎你学习python传入参数覆盖默认参数:
baba , 你好
消息是: 欢迎你学习python
baba , 你好
消息是: 恭喜你通过python等级考试

从上面程序可以看出,如果只传入一个位置参数,由于该参数位于第一位,系统会将该参数值传给name参数。因此,我们不能按如下方式调用say_hi()函数,例:

def say_hi (name = "virus", message = "欢迎你学习python"):print(name, ",", "你好")print("消息是:", message)say_hi("恭喜你通过python的等级考试")输出结果:
恭喜你通过python的等级考试 , 你好
消息是: 欢迎你学习python

上面调用时传入的 “恭喜你通过python的等级考试 ” 字符串将传给name参数,而不是message参数。我们也不能按如下方式来调用say_hi()函数,例:

def say_hi (name = "virus", message = "欢迎你学习python"):print(name, ",", "你好")print("消息是:", message)say_hi(name="hki", "恭喜你通过python等级考试")输出结果:
SyntaxError: positional argument follows keyword argument

因为python规定:关键字参数必须位于位置参数的后面,因此提示错误:positional argument follows keyword argument

参数收集(个数可变的参数)

很多编程语言都允许定义个数可变的参数,这样可以在调用函数时传入任意多个参数。python当然也不例外,python允许在形参前面添加一个星号(*),这样就意味该参数可接收多个参数值,多个参数值被当成元组传入,例:

def test(a, *books):print(books)for b in books :print(b)print(a)test(5, "abc", "bcs")输出结果:
('abc', 'bcs')
abc
bcs
5

从上面的运行结果可以看出,当调用 test() 函数时,books参数可以传入多个字符作为参数值。从 test() 的函数体代码来看,参数收集的本质就是一个元组:python会将传给 books 参数的多个值收集成一个元组。

python允许个数可变的形参可以处于形参列表的任意位置(不要求是形参列表的最后一个参数),但python要求一个函数最多只能带一个支持 “普通” 参数收集的形参,例:

def test(*books, a):print(books)for b in books :print(b)print(a)test("abc", "bcs", "yyds", a = 5)输出结果:
('abc', 'bcs', 'yyds')
abc
bcs
yyds
5

正如从上面程序中所看到的,test() 函数的第一个参数就是个数可变的形参,由于该参数可接收个数不等的参数值,因此如果需要给后面的参数传入参数值,则必须使用关键字参数;否则,程序会把所传入的多个值都当成是传给books参数的。

python还可以收集关键字参数,此时python会将这种关键字参数收集成字典。为了让python能收集关键字参数,需要在参数前面添加两个星号。在这种情况下,一个函数可用时包含一个支持“普通”参数收集的参数和一个支持关键字参数收集的参数,例:

def test(*books, **message):print(books)print(message)test("abc", "bcs", "yyds", a = 5, b = 85)输出结果:
('abc', 'bcs', 'yyds')
{'a': 5, 'b': 85}

逆向参数收集

所谓逆向参数收集,指的是在程序已有列表、元组、字典等对象的前提下,把它们的元素“拆开”后传给函数的参数。

逆向参数收集需要在传入的列表、元组参数之前添加一个星号,在字典参数之前添加两个星号,例:

def test(name, message):print("用户是:", name)print("欢迎信息:", message)my_list = ["virus", "欢迎来学习python"]test(*my_list)输出结果:
用户是: virus
欢迎信息: 欢迎来学习python
def test(name, message):print("用户是:", name)print("欢迎信息:", message)my_list = {"name":123, "message":"欢迎来学习python"}test(**my_list)输出结果:
用户是: 123
欢迎信息: 欢迎来学习python

函数的参数传递机制

python的参数值是如何传入函数的呢?这是由python函数的参数传递机制来控制的。python中函数的参数传递机制都是 “值传递”。所谓的值传递,就是将实际的参数值的副本(复制品)传入函数,而参数本身不会受到任何影响。例:

def chuandi (a, b):a, b = b, aprint("这是 chuandi 里的a:", a)print("这是 chuandi 里的b:", b)a = 10
b = 20
chuandi(a, b)
print("这是外面定义的a:", a)
print("这是外面定义的b:", b)输出结果:
这是 chuandi 里的a: 20
这是 chuandi 里的b: 10
这是外面定义的a: 10
这是外面定义的b: 20

变量的作用域

在程序中定义一个变量时,这个变量时有作用范围的,变量的作用范围被称为它的作用域。根据定义变量的位置,变量分为两种。
局部变量:在函数中定义的变量,包括参数,都被称为局部变量
全局变量:在函数外面、全局范围内定义的变量,被称为全局变量。
每个函数在执行时,系统都会为该函数分配一块 “临时内存空间”,所有的局部变量都被保存在这块临时内存空间内。当函数执行完成后,这块内存空间就被释放了,这些局部变量也就失效了,因此离开函数之后就不能再访问局部变量了。
全局变量意味着它们可以在所有函数内被访问。

不管是在函数的局部范围内还是在全局范围内,都可能存在多个变量,每个变量“持有”该变量的值。从这个角度来看,不管是局部范围还是全局范围,这些变量和它们的值就像一个“看不见”的字典,其中变量名就是字典的key,变量值就是字典的value。

实际上,python提供了如下三个工具函数来获取指定范围内的“变量字典”
globals():该函数返回全局范围内所有变量组成的“变量字典”
locals():该函数返回当前局部范围内所有变量组成的“变量字典”
vars():获取在指定对象范围内所有变量组成的“变量字典”,如果不传入object参数,vars()和locals()的作用完全相同。

globals() 和 locals() 看似完全不同,但它们实际上也是有联系的,关于这两个函数的区别和联系大致有以下两点:

locals() 总是获取当前局部范围内所有变量组成的 “变量字典”,因此,如果在全局范围内(在函数之外)调用 locals() 函数,同样会获取全局范围内所有变量组成的 “变量字典”;而 globals() 无论在哪里执行,总是获取全局范围内所有变量组成的 “变量字典”。

一般来说,使用locals()和globals()获取的“变量字典”只应该被访问,不应该被修改。但实际上,不管是使用globals()还是使用locals()获取的全局范围内的“变量字典”,都可以被修改,而这种修改会真正改变全局变量本身;但通过 locals() 获取的局部范围内的 “变量字典”,即使对它修改也不会影响局部变量。
例:

def test():age = 20print(locals()['age']) #输出20locals()['age'] = 12  #函数内改变 age 的值print("函数内age的值", age) #依然输出20globals()['x'] = 19test()
globals()['x'] = 89 #使用globals()全局函数改变 x 的值
print(x)输出结果:
20
函数内age的值 20
89

从上面程序可以清楚地看出,locals()函数用于访问特定范围内的所有变量组成的“变量字典”,而globals()函数则用于访问全局范围内的全局变量组成的“变量字典”。

全局变量默认可以在所有函数内被访问,但如果在函数中定义了与全局变量同名的变量,此时就会发生局部变量遮蔽全局变量的情形,例:

name = "Charlie"def test():print(name)name = "Virus" #这里遮蔽了test()
print(name)输出结果:
UnboundLocalError: local variable 'name' referenced before assignment

python语法规定:在函数内部对不存在的变量赋值时,默认就是重新定义新的局部变量。因此这行代码相当于重新定义了name局部变量,这样name全局变量就被遮蔽了。

为了避免这个问题,可以通过两种方式来修改上面程序
1、访问被遮蔽的全局变量

name = "Charlie"def test():print(globals()['name']) #访问被遮蔽的全局变量name = "Virus" #这里遮蔽了test()
print(name)输出结果:
Charlie
Charlie

2、在函数中声明全局变量

name = "Charlie"def test():global name #声明全局变量print(name)name = "Virus" #这里遮蔽了test()
print(name)输出结果:
Charlie
Virus

课外监督

最近一部分同学在后台私聊我说,自己每天都准备要学习了,但是一去到电脑桌上就是提不起劲来,怎么办呢?针对这种情况的同学,我决定每天花一点时间对你们学习进行监督和辅导,如有需要的同学,扫描下面的图片,点击 “联系作者” 进行报名。

结语

这节课主要要掌握好参数的收集和逆向收集,这两个点是很重要的,后面开发的时候都会经常用到,而且也要明白函数参数传递的机制,好啦,今节课就先讲到这里,下节课讲函数的局部函数,敬请期待。

《每天五分钟冲击python基础之函数参数》(十八)相关推荐

  1. 《每天五分钟冲击python基础之字符串练习题》(七)

    前言 相信通过上两节课的学习,同学们都已经能轻松掌握了,python字符串的入门和字符串的深入了,(ps:如果还没有学习的同学,请到这里先学习,再来看这节课喔!<每天五分钟冲击python基础之 ...

  2. python基础高级函数(十九)

    map的介绍: reduce的介绍: from functiontool import reduce filter介绍:

  3. python 基础列表解析(十八)

    # 列表解析:根据一个列表的解析快速生成另外一个列表 a = [1,2,3,4] # 新生成一个列表 b = [2,3,4,5] # 把元素从列表里面取出来,给b赋值 b = [item + 1 fo ...

  4. 五分钟学会python_关于五分钟学Python系列视频

    Up主记得我们父母辈考大学的时候,外语,尤其是英语,是一个非常火爆的专业.那个时候会英语的人相对比较少,因此能掌握流利的英文听说读写的学生可以算是稀缺人才.现在虽然英语专业人才仍然有很大市场,但是整体 ...

  5. python的用途实例-Python基础之函数原理与应用实例详解

    本文实例讲述了Python基础之函数原理与应用.分享给大家供大家参考,具体如下: 目标 函数的快速体验 函数的基本使用 函数的参数 函数的返回值 函数的嵌套调用 在模块中定义函数 01. 函数的快速体 ...

  6. Python基础之函数

    详情请戳 python基础之函数介绍及使用 python基础之内置函数 python基础之迭代器和生成器 python基础之装饰器 转载于:https://www.cnblogs.com/zhangl ...

  7. Python数据结构与算法(1.5)——Python基础之函数与异常

    Python数据结构与算法(1.5)--Python基础之函数与异常 0. 学习目标 1. 函数 1.1 自定义函数 1.2 函数与参数 1.3 函数与返回值 2. 异常处理 2.1 raise 语句 ...

  8. 《gcc五分钟系列》基础部分结束

    <gcc五分钟系列>基础部分结束 我把常用的编译选项都已经介绍完了.     本系列打算休息一段时间. 转载于:https://blog.51cto.com/elephantliu/828 ...

  9. 劢领AT| 五分钟,零基础玩转阿里云物联网套件

    劢领AT| 五分钟,零基础玩转阿里云物联网套件 阿里云准备工作 新建产品 添加设备 WIFI模块及设备连接 AT指令方式 配置网络 一步到位,直接连接阿里云 发布与订阅消息 订阅主题 说明 阿里云准备 ...

最新文章

  1. 都是程序员,凭什么他能站在鄙视链的顶端?
  2. Transformer t2t vit
  3. 为.netcore助力--WebApiClient正式发布core版本
  4. html 链接 id属性_HTML id属性
  5. 上海day3 ----
  6. Java语法基础学习DayTwo
  7. 系统集成项目管理工程师教程 第二版下载,仅供学习交流使用
  8. 160813_qt显示阿拉伯输入法9x7点阵
  9. is_enabled:selenium中判断元素是否可以使用;is_selected()/is_displayed()
  10. BP神经网络对鸢尾花进行分类
  11. 经营报表-FineReport配置Oracle外接数据库(2)
  12. MarkDown基本语法(标题,字体,引用,分割线、插入图片,超链接,列表,表格,插入代码标段)
  13. java就业前景,成都java培训,传智播客java培训
  14. 从0开始学java_从0开始学java-变量
  15. 如何解决Win10操作系统无法访问局域网共享文件夹的问题
  16. lcd命令 linux,嵌入式Linux裸机开发(十五)——LCD
  17. android 空包写入签名(OPPO、VIVO、小米等)
  18. 高分辨率遥感卫星影像在交通方面的应用及高分二号影像获取
  19. matlab psk 信号,急求···psk信号载频估计的matlab算法
  20. 管理学理论(SWOT分析等八种理论)

热门文章

  1. java虚拟机参数 -D、-X和-XX的区别
  2. JVM 启动参数规则:-、-X、-XX、-D表示什么意思?
  3. 一个疑惑的的问题-ntvdm.exe进程
  4. python学习笔记(一)数据处理
  5. 经典拼数字游戏NumPuzzle C# By Red_angelX
  6. php 亚马逊关键字排名,亚马逊提升关键词排名的方法
  7. TortoiseGit(小乌龟) git did not exit cleanly (exit code 1)
  8. MNIST导入图片数据集
  9. 【论文汇总】 ECCV 2020 语义分割paper汇总
  10. Warning:The `android.dexOptions.incremental` property is deprecated and it has no effect on the buil