我的Python入门笔记(13)
十章、函数(上)
If the implementation is hard to explain, it's a bad idea.——The Zen of Python
要把程序分解成较小的部分,主要有三种方法。函数(function)就像是代码的积木,可以反复使用,利用对象(object),可以把程序中的各部分描述为自包含的单元。模块(module)就是包含程序各部分的单独文件。函数是组织好的,可以重复使用的,用来实现单一或者关联功能的代码段。函数可以提高应用的模块性,和代码的重复利用率。
一、函数的创建和调用
1.创建一个函数
创建函数也称为定义函数,可以理解为创建一个具有某种用途的工具。使用def关键字实现,其语法格式如下:
def functionname([parameterlist]):
[‘’’comments’’’]
[functionbody]
functionname:函数名称,在调用函数时使用
paramenterlist:可选参数,用于指定向函数中传递的参数,如果有多个参数,各参数间使用逗号分隔,如果不指定,则表示该函数没有参数。在调用时,也不指定函数。
comments:可选参数,表示为函数指定注释,注释的内容通常是说明该函数的功能、要传递的参数的作用等,可以为用户提供友好的提示和帮助内容。
functionbody:可选参数,用于指定函数体,即该函数被调用后,要执行的功能代码,如果函数有返回值,可以使用return语句返回
函数没有参数时,也必须保留一对空的小括号,否则会报错。在定义函数时,如果指定了”comments”参数,那么在调用函数时,输入函数的名称及左侧的小括号时,就会显示该函数的帮助信息。函数体”functionbody”和注释”comments”相对于def关键字必须保留一定的缩进。
2.调用函数
调用函数就是执行函数,如果想把创建的函数理解为创建一个某种用途的工具,那么函数调用就相当于使用该工具,其语法格式如下:
functionname([paramentersvalue])
functionname:函数名称,要调用的函数名称,必须是已经创建好的
paramentersvalue:可选参数,用于指定各个参数的值,如果需要传递多个参数值,则各个参数值之间使用逗号分隔,如果该函数没有参数,则直接写一对小括号即可。
1 def filterchar(string):
2 """
3 :param string:过滤危险字符(如傻逼),并将过滤后的结果输出
4 :return: 没有返回值
5 """
6 import re
7 pattern = r'(傻逼)|(沙雕网友)'
8 sub=re.sub(pattern,'**',string)
9 print(sub)
10 about='我是来自最右的沙雕,但不是傻逼'
11 filterchar(about)
12 输出:
13 我是来自最右的沙雕,但不是***
3.pass空语句
在Python中有一个pass语句,表示空语句,它不做任何事情,一般起到占位作用。例如,创建一个函数,但是我们暂时不知道该函数要实现什么功能,这时候就可以使用pass语句填充函数的主体,表示“以后会填上”,示例如下:
1 def dunc(): 2 #pass
在python3中,允许在可以使用表达式的任何地方使用...(3个连续的点号)来省略代码,由于省略号自身什么都不做,因此,可以当做是pass语句的一种替代方案。
1 def func(): 2 ...
二、参数传递
在调用函数时,大多数情况下,主调函数和被调用函数之间有数据传递关系,这就是有参数的函数形式。函数参数的作用是传递数据给函数使用,函数利用接受的数据进行具体的操作处理。
1.形参和实参
在使用函数时,经常会用到形式参数(形参)和实际参数(实参)。形参和实参的区别。
形式参数:在定义函数时,函数名后面的括号中的参数为“形式参数”,也称为形参。
实际参数:在调用一个函数时,函数名后面的括号中的参数为“实际参数”,也就是将函数的调用者提供给函数的参数称为实际参数,也称之为实参。
根据实参类型的不同,可以分为将实参的值传递给形参,和将实参的引用传递给形参两种情况。其中,当实参为不可变对象时,进行的是值传递;当实参为可变对象时,进行的是引用传递。实际上,值传递和引用传递的基本区别就是,进行值传递后,改变形参的值,实参的值不变;而进行引用传递后,改变形参的值,实参的值也一同改变。
函数定义时参数列表中的参数就是形参,而函数调用时传递进来的参数就是实参。
2.位置参数
位置参数也称为必备参数,必须按照正确的顺序传到函数中,即调用时的数量和位置必须和定义时是一样的。
1.数量必须与定义时一致
在调用函数时,指定的实参数量必须与形参数量一致,否则将会抛出TypeError异常,提示缺少必要位置参数。例如:定义一个函数,该函数有三个参数,但在调用时值传递两个参数,则会提示报错。
2.位置必须与定义时一致:
在调用函数时,指定的实参位置必须与形参位置一致,否则将会产生以下两种结果:
1.抛出TypeError异常,
2.产生的结果与预期结果不一致(在调用函数时一定要确定好位置,否则容易产生bug,而且不容易被发现)
3.关键字参数
关键字参数是指使用形参的名字来确定输入的参数值。通过该方式指定实参时,不再需要与形参的位置一致,只要将参数名写正确即可。这样可以避免用户需要牢记参数位置的麻烦,使得函数的调用和参数的传递更加灵活方便.
4.为参数设置默认值
调用函数时,如果没有某个指定参数将抛出异常,即在定义函数时,直接指定形式参数的默认值。这样,当没有传入参数是,则直接使用定义函数时设置的默认值。其语法格式如下:
def functionname(…,[parameter1=defaultvalue]): [functionbody]
functionname:函数名称,在调用函数时使用
parameter1=defaultvalue:可选参数,用于指定向函数传递的参数,并且为该参数设置默认值为defaultvalue
functionbody:可选参数,用于指定函数体,即该函数被调用后,要执行的功能代码
在定义函数时,指定默认的形参必须在所有参数的最后,否则会产生语法错误。此外,在Python中,可以使用“函数名_defaults_”查看函数的默认值参数的当前值,其结果是一个元组。在使用可变对象作为函数参数的默认值时,多次调用可能会导致意料之外的情况。示例如下:
1 def demo(obj=[]): #定义函数并为参数obj指定默认值 2 print("obj的值:",obj) 3 obj.append(1) 4 demo() #调用demo函数 5 输出: 6 obj的值: []
1 demo() #在次调用 2 输出: 3 obj的值: [] 4 obj的值: [1]
这显然不是想要的结果,为防止出现这种情况,最好使用None作为可变对象的默认值,这时候还需要进行代码的检查。修改后如下:
1 def demo(obj=None): #定义函数并为参数obj指定默认值 2 if obj==None: 3 obj= [] 4 print("obj的值:",obj) 5 obj.append(1) 6 demo() #调用demo函数 7 demo() #在次调用 8 输出: 9 obj的值: [] 10 obj的值: []
定义函数时,为形式参数设置默认值要牢记:默认参数必须指向不可变对象。
5.可变参数
在Python中,还可以定义可变参数。可变参数也称为不定长参数,即传入函数中的实际参数可以是任意个,在定义可变参数时,主要有两种形式:一种是*parameter,另一种是**parameter。
1.*parameter
这种形式表示接收任意多个实际参数并将其放到一个元组中。例如,定义一个函数,让其可以接收任意多个实际参数。
1 def lovenum(*num): 2 print('\n我喜欢的数字有:',end=' ') 3 for item in num: 4 print(item,end=” ”) 5 lovenum('220') 6 lovenum('220','284','26') 7 lovenum('220','284','1210','1184') 8 输出: 9 我喜欢的数字有: 10 220 11 我喜欢的数字有: 12 220 284 26 13 我喜欢的数字有: 14 220 284 1210 1184
如果想使用一个已经存在的列表作为函数的可变参数,可以在列表的名称前加“*”
1 def lovenum(*num): 2 print('\n我喜欢的数字有:') 3 for item in num: 4 print(item,end=' ') 5 list1=[22,26,220,284] 6 lovenum(*list1) 7 输出: 8 我喜欢的数字有: 9 22 26 220 284
2.**parameter
这种形式表示接收任意多个显式赋值的实际参数,并将其放入一个字典中,示例,定义一个函数,让其可以接收任意多个显式赋值的实际参数,示例如下:
1 def lovenum(**num): 2 print() 3 for num1,num2 in num.items(): 4 print(num1+'喜欢的数字是:'+num2) 5 lovenum(雨霓同学='1210',淑雪同学='1184') 6 输出: 7 雨霓同学喜欢的数字是:1210 8 淑雪同学喜欢的数字是:1184
如果想要使用一个已经存在的字典作为函数的可变参数,可以在字典的名称前加“***”。示例如下:
1 def lovenum(**num): 2 print() 3 for num1,num2 in num.items(): 4 print(num1+'喜欢的数字是:'+num2) 5 dict1={'雨霓同学':'1210','淑雪同学':'1184','霜序':'220'} 6 lovenum(**dict1) 7 输出: 8 雨霓同学喜欢的数字是:1210 9 淑雪同学喜欢的数字是:1184 10 霜序喜欢的数字是:220