目录
Python函数
Python函数是一段可以重复利用的代码段。函数是一种简单封装,目的是实现某些功能。Python中有很多内置函数,比如print()具有打印功能,list()可以把元组转换成列表。下面要讲的Python函数是我们自己定义的函数。
Python函数的定义
Python函数的定义需要使用def关键字,格式如下:
def 函数名(参数列表):
函数体
示例程序如下
# 函数的定义
def myfun():
mystr="abc"
myint=123
str_joint=mystr+str(myint)
print(str_joint)
# 函数的调用,第1次
myfun()
# 函数的调用,第2次
myfun()
运行结果
C:UsershccmaAnaconda3python.exe E:/wkp01/p00/test01/py001/t09.py
abc123
abc123
Process finished with exit code 0
Python函数的调用
Python函数的调用就是直接写函数名(参数列表),注意函数名后面的括号不能省(即使参数列表是空)。
函数的定义只有一次,但是调用可以有多次。函数通过多次调用,达到了多次利用的目的。
如果函数定义时有参数列表,那么调用时需要把实际参数写入调用函数内(参看后面函数参数部分)。
Python函数的参数
Python函数的参数指的是函数定义时参数列表中的变量。这个变量有个特点,就像是点位符,定义时假想有这样的变量,只在在调用时才传入真正变量。当我们调用时,你传入不同参数,会得到不同结果,这样既能实现代码重复利用,又能得到想要的结果。
Python函数的参数有空参数(无参)、必需参数、默认参数,另外还有关键字参数和不定长参数(后面讲)。
函数定义时,参数列表中的参数,称为形参(形式上的参数)。
函数调用时,参数列表中的参数,称为实参(实际传入的参数)。形参与实参要对应,否则程序会出错。
下面程序是必需参数的函数定义与调用。
# 函数的定义
def myfun(param1,param2):
mystr=param1
myint=param2
str_joint=mystr+str(myint)
print(str_joint)
# 函数的调用,第1次
myfun("abc",123)
# 函数的调用,第2次
myfun("hello",11)
运行结果
C:UsershccmaAnaconda3python.exe E:/wkp01/p00/test01/py001/t09.py
abc123
hello11
Process finished with exit code 0
从上面程序可以看出,定义时假想了两个变量param1和param2,分别是str类型和int类型。然而,这里隐含了一个要求,就是调用时,写入的参数类型不能搞错,需要与函数定义时的类型一致才行,否则程序会出错。比如,调用时传入两个int类型时,这个程序会报错。
# 函数的定义
def myfun(param1,param2):
str_joint=param1+str(param2)
print(str_joint)
# 函数的调用,第1次
myfun("abc",123) # abc123
# 函数的调用,第2次
myfun(1234,123) # 报错 TypeError: unsupported operand type(s) for +: 'int' and 'str'
运行结果
C:UsershccmaAnaconda3python.exe E:/wkp01/p00/test01/py001/t09.py
abc123
Traceback (most recent call last):
File "E:/wkp01/p00/test01/py001/t09.py", line 12, in <module>
myfun(1234,123) # 报错 TypeError: unsupported operand type(s) for +: 'int' and 'str'
File "E:/wkp01/p00/test01/py001/t09.py", line 5, in myfun
str_joint=param1+str(param2)
TypeError: unsupported operand type(s) for +: 'int' and 'str'
Process finished with exit code 1
因此,调用带参数的函数时,需要注意参数要求。
当然,设计自定义函数时,可以尽量考虑这些问题,避免程序发生错误。比如,参数变量名取名时让人一看就知道需要传入什么类型数据,或者程序里面可以控制错误的出现。
参数变量名对数据类型的提示,程序如下。
# 函数的定义
def myfun(str_param1,int_param2):
str_joint=str_param1+str(int_param2)
print(str_joint)
# 函数的调用,第1次
myfun("abc",123) # abc123
# 函数的调用,第2次
myfun("1234",123) # 1234123
在程序里面处理可能发生的错误,比如将参数变量都利用str()函数转换成字符串,然后再拼接。
# 函数的定义
def myfun(param1,param2):
str_joint=str(param1)+str(param2)
print(str_joint)
# 函数的调用
myfun("abc",123) # abc123
myfun(1234,123) # 1234123
myfun("abc","abc") # abcabc
默认参数是指函数定义时给定了参数默认值,如果调用时不给新值,则函数运行时使用默认值,如果给了新值则程序运行时使用新值。
注意,定义时默认参数都需要排列在参数列表的最后。
# 函数的定义
def myfun(param1,param2=100):
str_joint=str(param1)+str(param2)
print(str_joint)
# 函数的调用
myfun("abc") # abc100 ,使用了默认参数
myfun("abc",123) # 1234123
Python函数的返回值与元组
Python函数的返回值使用return语句。可以返回空,也可以返回单个对象,另外Python带可以利用元组返回多个对象(这是很多其他编程语言不具备的)。
返回空对象
# 函数的定义
def myfun():
print("hello")
return
# 函数的调用
myfun() # hello
返回单个对象
# 函数的定义
def myfun(int_x):
myres=int_x+100
return myres
# 函数的调用,并返回结果
y=myfun(5)
print(y) # 105
返回多个结果(实际上是个元组)
# 函数的定义
def myfun(int_x,int_y):
myres1=int_x+100
myres2=int_y+200
return myres1,myres2
# 函数的调用,并返回结果(多个)
x,y=myfun(5,6)
print(x,y) # 105 206
Python函数的关键字参数与可变参数
Python函数的参数还有两种情况,作用不同,分别是关键字参数与可变参数。
关键字参数是指调用时通过关键字(形参名)来指定如何配对形参与实参。
关键字参数程序(不用担心形参变量定义先后顺序)
# 函数的定义
def myfun(int_x,int_y):
myres1=int_x+100
myres2=int_y+200
return myres1,myres2
# 函数的调用,并返回结果(多个)
x,y=myfun(5,6)
print(x,y) # 105 206
# 利用关键字参数,不用担心形参变量定义先后顺序
x,y=myfun(int_y=5,int_x=6)
print(x,y) # 106 205
可变参数是指参数列表中的参数个数可变。
可变参数分为两种:
- *args 接受任意多个实际参数
- **kwargs接收任意多个以关键字参数赋值的实际参数
可变参数程序(不用担心形参数量长度未知)
*args程序,接受任意多个实际参数。
# 函数的定义
def myfun(*args):
print(type(args),args)
for item in args:
print(item)
# 函数的调用
myfun(5,6)
myfun(5,6,7,8)
运行结果
C:UsershccmaAnaconda3python.exe E:/wkp01/p00/test01/py001/t09.py
<class 'tuple'> (5, 6)
5
6
<class 'tuple'> (5, 6, 7, 8)
5
6
7
8
Process finished with exit code 0
**kwargs程序,接收任意多个以关键字参数。
# 函数的定义
def myfun(**kwargs):
print(type(kwargs),kwargs)
for k,v in kwargs.items():
print(k,v)
# 函数的调用
myfun(num=1)
myfun(num=1,age=18)
myfun(num=1,name="zhangsan",age=18)
运行结果
C:UsershccmaAnaconda3python.exe E:/wkp01/p00/test01/py001/t09.py
<class 'dict'> {'num': 1}
num 1
<class 'dict'> {'num': 1, 'age': 18}
num 1
age 18
<class 'dict'> {'num': 1, 'name': 'zhangsan', 'age': 18}
num 1
name zhangsan
age 18
Process finished with exit code 0
Python函数参数的值传递与引用传递
值传递,传入函数内部的是值,函数内部对其操作不会影响到外面本身。比如,不可变类型int和str。不可变即不可修改,修改变后的变量内存是新地址,与原来变量无关联。
引用传递,传入函数内部的是变量地址,函数内对其操作时会改变外面本身的值。比如,可变类型list。可变即可修改,修改后变量内存地址不变,就是真正达到了修改此内存地址对应变量的值,不管在哪里(函数外或函数内),谁利用此变量地址修改变量值,都可以使变量值改变。引用,意思就是变量地址有关联,是相同的。这里延用了其他语言的叫法,引用就是变量地址,同指针,在Python中指的是可变类型变量。
值传递(不可变对象是作为形参),函数处理后,外部变量值不受影响(无修改)。
a=5
b="abc"
print("a,b地址:",id(a),id(b)) # a,b地址: 140705361076752 2128183209264
print("调用之前:",a,b) # 调用之前: 5 abc
def myfun1(fa,fb):
print("fa,fb地址:", id(fa), id(fb)) # fa,fb地址: 140705361076752 2450726038832
fa=fa+fa
fb=fb+fb
print("fa,fb地址:", id(fa), id(fb)) # fa,fb地址: 140705361076912 2128214799216
print("函数内部:",fa,fb) # 函数内部: 10 abcabc
myfun1(a,b)
print("调用之后:",a,b) # 调用之后: 5 abc
引用传递(可变对象是作为形参),函数处理后,外部变量值受影响(有修改)。
a=[5]
b=["abc"]
print("a,b地址:",id(a),id(b)) # a,b地址: 2002862336392 2002862363080
print("调用之前:",a,b) # 调用之前: [5] ['abc']
def myfun1(fa,fb):
print("fa,fb地址:", id(fa), id(fb)) # fa,fb地址: 2002862336392 2002862363080
fa[0]=fa[0]+fa[0]
fb[0]=fb[0]+fb[0]
print("fa,fb地址:", id(fa), id(fb)) # fa,fb地址: 2002862336392 2002862363080
print("函数内部:",fa,fb) # 函数内部: [10] ['abcabc']
myfun1(a,b)
print("调用之后:",a,b) # 调用之后: [10] ['abcabc']
Python函数的嵌套
Python函数可以嵌套,这也是很多其他语言中不具备的特点。
def myfun():
print("这是外层函数")
a=123
def innerFun():
print("这是内层函数")
print(a)
innerFun()
print("end")
myfun()