python学习-第5章 自定义功能单元(一)来自《21天学通Python》

第5章 自定义功能单元(一)
Python语言中已经内置了很多功能单元,其中最简单的功能单元就 是函数。在Python语言的交互式环境下可以看到内建函数有不少,包括 前面介绍的输入输出函数、数值类型转换函数、zip()、range()等迭代器 函数。那么,如果你想编程解决自己的实际问题,就需要自己定义相关函 数并调用它来完成相关功能。
本章主要介绍Python中自定义函数及调用的方法,内容包括: 声明函数; 调用自定义函数; 变量作用域; 各种类型的函数参数应用; 使用lambda建立匿名函数; Python其他常用内建函数。
5.1 使用函数
5.1.1 声明函数
python学习-第5章 自定义功能单元(一)来自《21天学通Python》_第1张图片(1)其中参数列表和返回值不是必须的,return后也可以不跟返回值, 甚至连return也没有。对于return后没有返回值的和没有return语句的函数 都会返回None值。
(2)有些函数可能既不需要传递参数,也没有返回值。
(3)没有参数时,包含参数的圆括号也必须写上,圆括号后也必须 有“:”。
(4)Python的函数比较灵活,与C语言中函数的声明相比,在Python中 声明一个函数不需要声明函数的返回值类型,也不需要声明参数的类 型。
例1:
python学习-第5章 自定义功能单元(一)来自《21天学通Python》_第2张图片

python学习-第5章 自定义功能单元(一)来自《21天学通Python》_第3张图片例2:
python学习-第5章 自定义功能单元(一)来自《21天学通Python》_第4张图片(1)tpl_sum()函数可知,当初定义的目的是求一个元组中所有数的和并返回的函数,而函数声明中的参数并没有指定参数的类型。 实际上,调用该函数的时候,不仅可以向其传递一个元组,也可以向其 传递一个列表,同样可以对列表进行求和。通过阅读该函数的程序代码,你会发现,如果该函数的参数T为列表时,函数体中的语句仍然是可以正常工作的。因此,你在调用这个函数时,提供的参数不管参数为一个列表,还是一个元组,函数都被正确的执行。
(2)当然,这并不表示可以向函数传递任何参数,这主要还是取决于函数的实现,在tpl_sum()函数中,只使用了for循环语句来遍历传入的参 数,并累加传入参数中的元素,只要传入的参数可以遍历,for循环就能够正确执行,因此,该函数才得以正确执行。但是,如果调用时所给参数的元组或列表中的元素不是整数、浮点数或单纯的字符串,则无法实 现加法,这就会导致调用该函数时的运行失败,并且这也意味着一旦出现问题只有在程序运行的时候才能被发现。

5.1.2 调用函数
(1)输入函数(input())和输出函数(print())的使用时,就是在调用Python 的内建函数。
(2)而调用自己定义的函数与调用内建函数标准库中的函数 方法都是相同的,要调用指定的函数就在语句中使用函数名,并且在函 数名之后用圆括号将调用参数括起来,而多个参数之间则用逗号隔开。
(3)调用自定义函数与内建函数不同点在于自定义函数调用前必须先声明函 数。
(4)如果调用函数的函数没有参数,也必须在函数名后给出圆括号。
(5)Python在实际调用函数的过程中也非常得灵活,不必为不同类型的 参数声明多个函数,在处理不同类型数据的时候可以调用相同的函数, 大部分情况都可以用同一个函数调用不同的数据类型。
5.2 深入函数
在调用某些函数,既可以向其传递参数,也可以不传递参数,函数依然可以正确调用;还有一些情况,比如函数中的参数数 量不确定,可能为1个,也可能为几个、甚至几十个。对于这些函数, 应该怎么定义其参数呢?
5.2.1 默认值参数
(1)在Python中,可以在声明函数的时候,预先为参数设置一个默认值,当调用函数,如果某个参数具有默认值,则可以不向函数传递该参数,这时,函数将使用声明函数时为该参数设置的默认值来运行。
声明一个参数具有默认值的函数形式如下:
def <函数名> (参数=默认值): <语句>
例3:
python学习-第5章 自定义功能单元(一)来自《21天学通Python》_第5张图片例4:如果声明一函数时,其参数列表中既包含无默认值参数,又包含有 默认值的参数,那么在声明函数的参数时,必须先声明无默认值参数, 后声明有默认值参数。
在这里插入图片描述
以上错误提示说明:在声明函数test()时,参数列表中,有具有默认 值参数之后还有无具有默认值参数,就发生了语法错误。
例5:如果一个函数具有多个参数,而且这些参数都具有默认值,在调用函数的时候,可能仅想向最后一个参数传递值,该怎么办?
python学习-第5章 自定义功能单元(一)来自《21天学通Python》_第6张图片
从输出可以看出,在Python中传递参数是按照声明函数时定义的参数的顺序依次传递的。第一次调用时只给了一个参数"Jonson",结 果是变量hi得到了它,name变量没有得到并且被赋予了默认值。第二次 调用时给了两个参数,变量hi、name按照顺序依次得到了调用时给的参数值。要想将调用时仅给的一个参数赋予第二个变量,就必须向指定的参数传递值。
5.2.2 参数传递
(1)在Python中参数值的传递是按照声明函数时参数的位置顺序进行传递的,即位置参数,调用时提供的第一个参数值会被声明时的参数列表中的第一个参数获取,其他的参数结合方法依次类推。而实际上Python 还提供了另外一种传递参数的方法——按照参数名传递值的方法,即提供关键字参数,提供关键字参数的函数调用类似于定义函数时设置参数的默认值。
(2)提供关键字参数调用函数时,要在调用函数名后的圆括号里写出形 式为“关键字=参数值”的参数,这样,调用函数时提供参数就不必严格 按照该函数声明时的参数列表的顺序来提供调用参数了。如果在函数调 用时,既提供了关键字参数,又提供了位置参数,则位置参数会被优先 使用,如果参数结合时出现重复,则会发生运行错误。
(3)调用函数提供参数时,按顺序传递的参数要位于关键字参数之 前,而且不能有重复的情况。
例6:
python学习-第5章 自定义功能单元(一)来自《21天学通Python》_第7张图片根据以上情况可知:一般来说,定义的函数如果既有无默认值的函数,又有有默认值的函数,应当把有默认值的参数放在后面。这样在调 用函数时,前面的无默认值的参数就可以依次序取得调用时所给的值。 对于默认值参数,没有依次取得时,就使用默认值,给函数调用带来很 大的方便。
5.2.3 可变数量参数传递
在自定义函数时,如果参数名前加上一个星号“*”,则表示该参数 就是一个可变长参数。在调用该函数时,如果依次序将所有的其他变量 都赋予值之后,剩下的参数将会收集在一个元组中,元组的名称就是前 面带星号的参数名。
例7:
python学习-第5章 自定义功能单元(一)来自《21天学通Python》_第8张图片
【代码说明】代码中定义了一个函数change_para_num(*tpl),它 只有一个带星号参数的函数。
【运行效果】如例7所示,两次调用第一行输出类型为tuple,即元组;第一次调用时只有一个参数,元组中也只有一个值;第二次调用 时有三个参数,全部收集到了tpl变量中。

当自定义函数时,参数中含有前面所介绍的三种类型的参数,则一 般来说带星号的参数应放在最后。当带星号的参数放在最前面时,仍然 可以正常工作,但调用时后面的参数必须以关键字参数方式提供,否则 因其后的位置参数无法获取值而引发错误。
例8:
python学习-第5章 自定义功能单元(一)来自《21天学通Python》_第9张图片
【代码说明】代码中定义的函数change_para_num()有三种类型的参 数,并且带星号的参数放在最前面。第一次调用时给出了3个位置参数 和一个关键字参数,因此tpl变量收集了1、2、3作为一个元组,而变量a 则取得值5,变量b则使用了默认值;第二次调用没有提供关键字参数, 无默认值的参数a没有获取到值,所以调用失败。
使用元组来收集参数的参数时,调用时提供的参数不能为关键字参 数,如果要收集不定数量的关键字参数可以在自定义函数时的参数前加 两颗星即valuename,这样一来,多余的关键字参数就可以以字典的 方式被收集到变量valuename之中。**
收集关键字参数时要放在函数声明的参数列表中的所有参数之 后。
例9:
python学习-第5章 自定义功能单元(一)来自《21天学通Python》_第10张图片
【代码说明】代码中定义了函数change_para_dct(),其最后一个参 数前有两颗星号,即为收集关键字参数到字典中。调用时,给出两个多 余的关键字参数,运行时会被放入名称为adct的字典中。
这种收集字典的方式为函数中使用大量的默认值提供了方便,不用 把大量的默认值全放在函数声明的参数中,而是把它放入程序中。
例10:
python学习-第5章 自定义功能单元(一)来自《21天学通Python》_第11张图片
【代码说明】代码中定义了一个函数cube(),其参数为两个,第一 个是普通参数name,第二个为收集关键字参数。函数体中给了一个默认 参数的字典,然后用字典的updae()函数将调用时提供的关键字参数更新 至默认参数的字典。以后的应用中,直接从字典获取即可。最后用三种 不同参数的方式调用cube函数。
5.2.4 拆解序列的函数调用
(1)前面使用函数调用时提供的参数都是位置参数和关键字参数,实际 上调用函数时还可以把元组和字典进行拆解调用。
(2)拆解元组提供位置参数; 拆解字典提供关键字参数。
(3)调用时使用拆解元组的方法是在调用时提供的参数前加一个
(star)号; 要拆解字典必须在提供的调用参数前加两个
(star)号。**
例11:
python学习-第5章 自定义功能单元(一)来自《21天学通Python》_第12张图片
5.2.5 函数调用时参数的传递方法
(1)Python中的元素有可变和不可变之分,如整数、浮点数、字符串、 元组等都属于不可变的;而列表和字典都属于可变的。
(2)在本书的3.1.6节中介绍“=”时 说,“=”号的作用是将对象引用与内存中某对象进行绑定,既然整数是不可变的,那么怎么改变一个指向整数的变量的值的呢?答案是直接在内存中创建一个新的整数值,然后将变量引用与其绑定,这虽然本质上的其他高级语言不同,(?)但在使用上是看不出什么差别的,但若将其提供 给函数作为参数,则效果不同。
(3)在函数调用时,若提供的是不可变参数,那么在函数内部对其修改 时,在函数外部其值是不变的;若提供是可变参数,则在函数内部对它 修改时,在函数外部其值也会改变的。
例12:
python学习-第5章 自定义功能单元(一)来自《21天学通Python》_第13张图片
【代码说明】代码中定义了一个修改提供参数的函数change(),参 数包括一个整数和一个列表。在调用前定义并输出了一个整数aint和一 个列表alst,然后把他们作为参数调用change(),最后输出两个变量的 值。
【运行效果】如图例12所示,在调用前后不可变量aint的值虽然在 函数内部进行了改变,但函数退出后其值仍然不变;而可变的列表alst 则完全不同,在调用函数后,显示了函数内的一切改变都应用了。但是 在函数中,可变的和不可变的量的值的改变是应用的。

列表、字典是可变对象,它在作为函数的默认参数时要注意一 个“陷阱”。
例13:
python学习-第5章 自定义功能单元(一)来自《21天学通Python》_第14张图片
【代码说明】代码中只定义了一个带有空列表默认参数的函数 myfun(),然后在不提供参数的情况下调用了三次这个函数。
如果要实现空列表的默认参数,可以修改函数代码如下:
例14:
python学习-第5章 自定义功能单元(一)来自《21天学通Python》_第15张图片

5.3 变量的作用域
在Python中,作用域可以分为:
(1)内置作用域:Python预先定义的;
(2)全局作用域:所编写的整个程序;
(3)局部作用域:某个函数内部范围。

每次执行函数,都会创建一个新的命名空间,这个新的命名空间就 是局部作用域,同一函数不同时间运行,其作用域是独立的,不同的函 数也可以具有相同的参数名,其作用域也是独立的。在函数内已经声明 的变量名,在函数以外依然可以使用。并且在程序运行的过程中,其值 并不相互影响。
例15:
python学习-第5章 自定义功能单元(一)来自《21天学通Python》_第16张图片
【代码说明】代码中在函数中声明了变量a,其值为整数类型;在 函数外声明了同名变量a,其值为字符串。在调用函数前后,函数外声 明的变量a的值不变。在函数内可以对a的值进行任意操作,它们互不影 响。
上述实例中两个变量a处于不同的作用域中,所以互不影响,但是 如前述,如果将全局作用域中的变量作为函数的参数引用,则是 不同的,但这两者不属于同一问题范畴。
但是,还有一种方法使函数中引用全局变量并进行操作,如果要在 函数中使用函数外的变量,可以在变量名前使用global关键字。
例16:
python学习-第5章 自定义功能单元(一)来自《21天学通Python》_第17张图片
【代码说明】示例代码仅在函数myfun()声明中增加了一句,就使 函数内使用的变量a成为全局变量。
在局部作用域内可以引用全局作用域内的变量,但不可以修改它。
例17:
python学习-第5章 自定义功能单元(一)来自《21天学通Python》_第18张图片
以上代码引发的错误是局部变量在分配前不能引用,原因是与 Python中的变量查找有关,在此外代码中函数内声明了a变量并初始 化,所以a被判为局部变量,但却之前在print(a)中引用了它。
5.4 使用匿名函数(lambda)
lambda可以用来创建匿名函数,也可以将匿名函数赋给一个变量供 调用,它是Python中一类比较特殊的声明函数的方式,lambda来源于 LISP语言,其语法形式如下: lambda params:expr
其中params相当于声明函数时的参数列表中用逗号分隔的参数, expr是函数要返回值的表达式,而表达式中不能包含其他语句(?),也可以返回元组(要用括号),还允许在表达式中调用其他函数。
例18:
在这里插入图片描述
lambda一般用来定义以下类型的函数:
简单匿名函数写起来快速而简单,省代码;
不复用的函数在有些时候需要一个抽象简单的功能,又不想单独定义一个函数;
为了代码清晰 有些地方使用它,代码更清晰易懂。 比如在某个函数中需要一个重复使用的表达式,就可以使用lambda 来定义一个匿名函数,多次调用时,就可以少写代码,但条理清晰。
5.5 Python常用内建函数
在Python中,没有导入任何模块或包时Python运行时提供的函数称 为内建函数,除了前面介绍的函数以外,常用内建函数如表5.1所示。python学习-第5章 自定义功能单元(一)来自《21天学通Python》_第19张图片例19:
python学习-第5章 自定义功能单元(一)来自《21天学通Python》_第20张图片
5.6 小结 本章主要介绍了Python语言中定义函数的相关知识。首先介绍了基 本的函数声明和调用方法,其次介绍了函数定义中的各种类型参数的定 义方法及调用时如何提供对应的参数值、变量的作用域;最后介绍了 lambda及常用内建函数。通过学习本章你应重点掌握函数的基本定义方 法及各种类型参数的定义,调用时如何给函数提供不同类型的参数。
二、实验题
1.自定义函数实现对列表中的数值进行排序。
2.自定义函数实现计算字符串中空格的个数。
python学习-第5章 自定义功能单元(一)来自《21天学通Python》_第21张图片
4.自定义函数实现对用户的登录验证,假设所有用户信息存放在 列表中形式如下: [{‘name’:‘john’,‘password’:‘2354kdd’,‘usertype’:1},…] 验证成功返回用户类型,否则返回0。

你可能感兴趣的:(Python自学,python)