Python函数

本文介绍了Python中函数的概念和重要性,详细讲解了如何创建和调用函数,包括函数的参数传递机制,如位置参数、关键字参数和默认值。此外,还探讨了形式参数和实际参数的区别,以及值传递和引用传递的差异。文章还提到了可变参数的使用,以及如何通过lambda表达式创建匿名函数。最后,讨论了变量的作用域,包括局部变量和全局变量的使用规则。
摘要由CSDN通过智能技术生成

 在前面的章节中,所有编写的代码都是从上到下依次执行的,如果某段代码需要多次使用,那么需要将该段代码复制多次,这种做法势必会影响开发效率,在实际项目开发中是不可取的。在Python中,提供了函数解决这种问题。我们可以把实现某一功能的代码定义为一个函数,然后在需要使用时,随时调用即可,十分方便。对于函数,简而言之就是可以完成某项工作的代码块,有点类似积木块,可以反复使用。

6.1 函数的创建和调用

6.1.1 创建一个函数
创建函数也称为定义函数,可以理解为创建一个具有某种用途的工具。使用def关键字实现,具体的语法格式如下:
def functionname([parameterlist]):    ['''comments''']    [functionbody]
参数说明:■ functionname:函数名称,在调用函数时使用。■ parameterlist:可选参数,用于指定向函数中传递的参数。如果有多个参数,各参数间使用逗号“,”分隔。如果不指定,则表示该函数没有参数,在调用时也不指定参数。注意:即使函数没有参数,也必须保留一对空的“()”,否则将显示如图6.1所示的错误提示对话框。

■ '''comments''':可选参数,表示为函数指定注释,注释的内容通常是说明该函数的功能、要传递的参数的作用等,可以为用户提供友好提示和帮助的内容。说明:在定义函数时,如果指定了'''comments'''参数,那么在调用函数时,输入函数名称及左侧的小括号时,就会显示该函数的帮助信息

注意:如果在输入函数名和左侧括号后,没有显示友好提示,那么就检查函数本身是否有误,检查方法可以是在未调用该方法时,先按下快捷键<F5>执行一遍代码。■ functionbody:可选参数,用于指定函数体,即该函数被调用后,要执行的功能代码。如果函数有返回值,可以使用return语句返回。注意:函数体“functionbody”和注释“'''comments'''”相对于def关键字必须保持一定的缩进。说明:如果想定义一个什么也不做的空函数,可以使用pass语句作为占位符。

6.1.2 调用函数

调用函数也就是执行函数。如果把创建的函数理解为创建一个具有某种用途的工具,那么调用函数就相当于使用该工具。调用函数的基本语法格式如下:functionname([parametersvalue])
参数说明:■ functionname:函数名称,要调用的函数名称必须是已经创建好的。■ parametersvalue:可选参数,用于指定各个参数的值。如果需要传递多个参数值,则各参数值间使用逗号“,”分隔。如果该函数没有参数,则直接写一对小括号即可。

6.2 参数传递
在调用函数时,大多数情况下,主调函数和被调用函数之间有数据传递关系,这就是有参数的函数形式。

6.2.1 了解形式参数和实际参数
在使用函数时,经常会用到形式参数和实际参数,二者都叫作参数,

1.通过作用理解

■ 形式参数:在定义函数时,函数名后面括号中的参数为“形式参数”。■ 实际参数:在调用一个函数时,函数名后面括号中的参数为“实际参数”,也就是将函数的调用者提供给函数的参数称为实际参数。

75972eaa5e8f40048fcc43d042c462c1.png

根据实际参数的类型不同,可以分为将实际参数的值传递给形式参数和将实际参数的引用传递给形式参数两种情况。其中,当实际参数为不可变对象时,进行值传递;当实际参数为可变对象时,进行的是引用传递。实际上,值传递和引用传递的基本区别就是,进行值传递后,改变形式参数的值,实际参数的值不变;而进行引用传递后,改变形式参数的值,实际参数的值也一同改变。

# 定义函数def demo(obj):    print("原值:",obj)
    obj += obj
# 调用函数print("=========值传递========")mot = "唯有在被追赶的时候,你才能真正地奔跑。"print("函数调用前:",mot)demo(mot) # 采用不可变对象——字符串print("函数调用后:",mot)print("=========引用传递 ========")list1 = ['绮梦','冷伊一','香凝','黛兰']print("函数调用前:",list1)demo(list1) # 采用可变对象——列表print("函数调用后:",list1)
上面代码的执行结果如下:=========值传递========函数调用前: 唯有在被追赶的时候,你才能真正地奔跑。原值: 唯有在被追赶的时候,你才能真正地奔跑。函数调用后: 唯有在被追赶的时候,你才能真正地奔跑。
=========引用传递 ========函数调用前: ['绮梦', '冷伊一', '香凝', '黛兰']原值: ['绮梦', '冷伊一', '香凝', '黛兰']函数调用后: ['绮梦', '冷伊一', '香凝', '黛兰', '绮梦', '冷伊一', '香凝', '黛兰']
从上面的执行结果中可以看出,在进行值传递时,改变形式参数的值后,实际参数的值不改变;在进行引用传递时,改变形式参数的值后,实际参数的值也发生改变。
2.通过一个比喻来理解形式参数和实际参数
函数定义时参数列表中的参数就是形式参数,而函数调用时传递进来的参数就是实际参数。就像剧本选主角一样,剧本的角色相当于形式参数,而演角色的演员就相当于实际参数。

6.2.2 位置参数
位置参数也称必备参数,是必须按照正确的顺序传到函数中,即调用时的数量和位置必须和定义时是一样的。
1.数量必须与定义时一致
在调用函数时,指定的实际参数的数量必须与形式参数的数量一致,否则将抛出TypeError异常,提示缺少必要的位置参数。

2.位置必须与定义时一致
在调用函数时,指定的实际参数的位置必须与形式参数的位置一致,否则将产生以下两种结果。

■ 抛出TypeError异常
抛出异常的情况主要是因为实际参数的类型与形式参数的类型不一致,并且在函数中,这两种类型还不能正常转换。

■ 产生的结果与预期不符
在调用函数时,如果指定的实际参数与形式参数的位置不一致,但是它们的数据类型一致,那么就不会抛出异常,而是产生结果与预期不符的问题。

说明:由于调用函数时,传递的实际参数的位置与形式参数的位置不一致时,并不会总是抛出异常,所以在调用函数时一定要确定好位置,否则产生Bug,还不容易被发现。

6.2.3 关键字参数
关键字参数是指使用形式参数的名字来确定输入的参数值。通过该方式指定实际参数时,不再需要与形式参数的位置完全一致。只要将参数名写正确即可。这样可以避免用户需要牢记参数位置的麻烦,使得函数的调用和参数传递更加灵活方便。

虽然在指定实际参数时,顺序与定义函数时不一致,但是运行结果与预期是一致的。

6.2.4 为参数设置默认值
调用函数时,如果没有指定某个参数将抛出异常,为了解决这个问题,我们可以为参数设置默认值,即在定义函数时,直接指定形式参数的默认值。这样,当没有传入参数时,则直接使用定义函数时设置的默认值。定义带有默认值参数的函数的语法格式如下:
def functionname(…,[parameter1 = defaultvalue1]):    [functionbody]
参数说明:■ functionname:函数名称,在调用函数时使用。■ parameter1 = defaultvalue1:可选参数,用于指定向函数中传递的参数,并且为该参数设置默认值为defaultvalue1。■ functionbody:可选参数,用于指定函数体,即该函数被调用后,要执行的功能代码。注意:在定义函数时,指定默认的形式参数必须在所有参数的最后,否则将产生语法错误。

多学两招:在Python中,可以使用“函数名.__defaults__”查看函数的默认值参数的当前值,其结果是一个元组。

另外,使用可变对象作为函数参数的默认值时,多次调用可能会导致意料之外的情况。

说明:定义函数时,为形式参数设置默认值要牢记一点:默认参数必须指向不可变对象。

6.2.5 可变参数
在Python中,还可以定义可变参数。可变参数也称不定长参数,即传入函数中的实际参数可以是任意多个。
定义可变参数时,主要有两种形式:一种是*parameter,另一种是**parameter。
1.*parameter
这种形式表示接收任意多个实际参数并将其放到一个元组中。例如,定义一个函数,让其可以接收任意多个实际参数,代码如下:def printcoffee(*coffeename): # 定义输出我喜欢的咖啡名称的函数    print('\n我喜欢的咖啡有:')    for item in coffeename:        print(item) # 输出咖啡名称
调用3次上面的函数,分别指定不同的实际参数,代码如下:
printcoffee('蓝山')
printcoffee('蓝山', '卡布奇诺', '土耳其', '巴西', '哥伦比亚')
printcoffee('蓝山', '卡布奇诺', '曼特宁', '摩卡')

如果想要使用一个已经存在的列表作为函数的可变参数,可以在列表的名称前加“*”。例如下面的代码:
param = ['蓝山', '卡布奇诺', '土耳其'] # 定义一个列表
printcoffee(*param) # 通过列表指定函数的可变参数
通过上面的代码调用printcoffee()函数后,将显示以下运行结果:
我喜欢的咖啡有:
蓝山
卡布奇诺
土耳其

2.**parameter
这种形式表示接收任意多个类似关键字参数一样显式赋值的实际参数,并将其放到一个字典中。例如,定义一个函数,让其可以接收任意多个显式赋值的实际参数,代码如下:def printsign(**sign): # 定义输出姓名和星座的函数    print() # 输出一个空行    for key, value in sign.items(): # 遍历字典        print("[" + key + "] 的星座是:" + value) # 输出组合后的信息
调用两次printsign()函数,代码如下:printsign(绮梦='水瓶座', 冷伊一='射手座')printsign(香凝='双鱼座', 黛兰='双子座', 冷伊一='射手座')

如果想要使用一个已经存在的字典作为函数的可变参数,可以在字典的名称前加“**”。例如下面的代码:dict1 = {'绮梦': '水瓶座', '冷伊一': '射手座','香凝':'双鱼座'} # 定义一个字典printsign(**dict1) # 通过字典指定函数的可变参数
通过上面的代码调用printsign()函数后,将显示以下运行结果:[绮梦] 的星座是:水瓶座[冷伊一] 的星座是:射手座[香凝] 的星座是:双鱼座

6.3 返回值

到目前为止,我们创建的函数都只是为我们做一些事,做完了就结束。但实际上,有时还需要对事情的结果进行获取。

为函数设置返回值的作用就是将函数的处理结果返回给调用它的程序。
在Python中,可以在函数体内使用return语句为函数指定返回值,该返回值可以是任意类型,并且无论return语句出现在函数的什么位置,只要得到执行,就会直接结束函数的执行。
return语句的语法格式如下:return [value]
参数说明:■ value:可选参数,用于指定要返回的值,可以返回一个值,也可返回多个值。
为函数指定返回值后,在调用函数时,可以把它赋给一个变量(如result),用于保存函数的返回结果。如果返回一个值,那么result中保存的就是返回的一个值,该值可以为任意类型。如果返回多个值,那么result中保存的是一个元组。说明:当函数中没有return语句时,或者省略了return语句的参数时,将返回None,即返回空值。

6.4 变量的作用域
变量的作用域是指程序代码能够访问该变量的区域,如果超出该区域,再访问时就会出现错误。在程序中,一般会根据变量的“有效范围”将变量分为“全局变量”和“局部变量”。

6.4.1 局部变量
局部变量是指在函数内部定义并使用的变量,它只在函数内部有效。即函数内部的名字只在函数运行时才会创建,在函数运行之前或者运行完毕之后,所有的名字就都不存在了。所以,如果在函数外部使用函数内部定义的变量,就会出现抛出NameError异常。
例如,定义一个名称为f_demo的函数,在该函数内部定义一个变量message(称为局部变量),并为其赋值,然后输出该变量,最后在函数体外部再次输出message变量,代码如下:def f_demo():    message = '唯有在被追赶的时候,你才能真正地奔跑。'    print('局部变量message =',message) # 输出局部变量的值f_demo() # 调用函数print('局部变量message =',message) # 在函数体外输出局部变量的值
运行上面的代码将显示异常。

de3a7abb52294dd6ba4114f695c7eb8d.png

 6.4.2 全局变量
与局部变量对应,全局变量为能够作用于函数内外的变量。全局变量主要有以下两种情况:
(1)如果一个变量,在函数外定义,那么不仅在函数外可以访问到,在函数内也可以访问到。在函数体以外定义的变量是全局变量。

说明:当局部变量与全局变量重名时,对函数体的变量进行赋值后,不影响函数体外的变量。

(2)在函数体内定义,并且使用global关键字修饰后,该变量也就变为全局变量。在函数体外也可以访问到该变量,并且在函数体内还可以对其进行修改。

那么想要在函数体内部改变全局变量的值,需要在定义局部变量时,使用global关键字修饰。

message = '唯有在被追赶的时候,你才能真正地奔跑。' # 全局变量print('函数体外:message =',message) # 在函数体外输出全局变量的值def f_demo():
    global message # 将message声明为全局变量    message = '命运给予我们的不是失望之酒,而是机会之杯。' # 全局变量    print('函数体内:message =',message) # 在函数体内输出全局变量的值f_demo() # 调用函数print('函数体外:message =',message) # 在函数体外输出全局变量的值
执行上面的代码后,将显示以下内容:
函数体外:message = 唯有在被追赶的时候,你才能真正地奔跑。
函数体内:message = 命运给予我们的不是失望之酒,而是机会之杯。
函数体外:message = 命运给予我们的不是失望之酒,而是机会之杯。
从上面的结果中可以看出,在函数体内部修改了全局变量的值。注意:尽管Python允许全局变量和局部变量重名,但是在实际开发时,不建议这么做,因为这样容易让代码混乱,很难分清哪些是全局变量,哪些是局部变量。

6.5 匿名函数(lambda)
匿名函数是指没有名字的函数,应用在需要一个函数,但是又不想费神去命名这个函数的场合。通常情况下,这样的函数只使用一次。在Python中,使用lambda表达式创建匿名函数,其语法格式如下:
result = lambda [arg1 [,arg2,……,argn]]:expression
参数说明:■ result:用于调用lambda表达式。■ [arg1 [,arg2,……,argn]]:可选参数,用于指定要传递的参数列表,多个参数间使用逗号“,”分隔。■ expression:必选参数,用于指定一个实现具体功能的表达式。如果有参数,那么在该表达式中将应用这些参数。注意:使用lambda表达式时,参数可以有多个,用逗号“,”分隔,但是表达式只能有一个,即只能返回一个值。而且也不能出现其他非表达式语句(如for或while)。

例如,要定义一个计算圆面积的函数,常规的代码如下:import math # 导入math模块def circlearea(r): # 计算圆面积的函数    result = math.pi*r*r # 计算圆面积
    return result # 返回圆的面积
r = 10 # 半径print('半径为',r,'的圆面积为:',circlearea(r))
执行上面的代码后,将显示以下内容:半径为 10 的圆面积为: 314.1592653589793
使用lambda表达式的代码如下:import math # 导入math模块r = 10 # 半径result = lambda r:math.pi*r*r # 计算圆的面积的lambda表达式print('半径为',r,'的圆面积为:',result(r))

从上面的示例中可以看出,虽然使用lambda表达式比使用自定义函数的代码减少了一些,但是在使用lambda表达式时,需要定义一个变量,用于调用该lambda表达式,否则将输出类似的结果:<function <lambda> at 0x0000000002FDD510>
这看似有点画蛇添足。那么lambda表达式具体应该怎么应用?实际上,lambda的首要用途是指定短小的回调函数。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小程序员.¥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值