在定义函数时,如果有些参数存在默认值,即部分参数不一定需要调用程序输入,可以在定义函数时直接为这些参数指定默认值。这时候当我们调用函数时,如果没有传入对应的参数值,那么这时候程序就会用之前的默认值来替代在这个参数,参见下面例子:
def leju(str,times = 2):
print(str*times)
leju(“hello~”)
输出结果如下:
def leju(str,times = 2):
print(str*times)
leju(“hello~”,4)
输出结果如下:
由于函数调用时需要按顺序输入参数,可选参数必须定义在非可选参数的后面,即leju()函数中带默认值的可选参数times必须定义在str参数后面。
在函数定义时,也可以设计可变数量参数,通过在参数前增加星号(*)来实现。注意,带有星号的可变参数只能出现在参数列表的最后。调用时,这些参数被当作元组类型传递到函数中,参见下面例子:
defleju(a, *b):
print(type(b))
forn inb:
a += n
returna
print(leju(1,2,3,4,5))
输出结果:
leju()函数定义了可变参数b,调用leju()函数时输入的(2,3,4,5)被当作元组传递给b,与a累加后输出。
关于参数的位置与名称传递,在进行函数调用时,实参默认采用按照位置顺序的方式传递给函数,例如一开始的程序中leju(“hello”,4)中第一个实参默认赋值给形参str,第二个实参赋值给形参times。这种按照位置传递参数的方法固然很好,但当参数很多时,这种调用参数的方式可读性较差。假设func()函数有6个参数,它的定义如下,其中参数分别表示两组三维坐标值。
func(x1,y1,z1,x2,y2,z2):
return
它的一个实际调用如下:
result = func(1,2,3,4,5,6)
这样问题来了。如果只是看实际调用而不看函数定义,很难理解这些输入参数的含义。在规模稍大的程序中,函数定义可能在函数库中,也可能与调用相距很远,带来的可读性较差。为了解决上述问题,Python提供了按照形参名称输入实参的方式,此时函数调用如下:
result = func(x2=4,y2=5,z2=6,x1=1,y1=2,z1=3)
由于调用函数时指定了参数名称,所以参数之间的顺序可以任意调整。
有关函数的返回值,return语句用来退出函数并将程序返回到函数被调用的位置继续执行。return语句可以同时将0个,1个或多个函数运算后的结果返回给函数被调用处的变量,如下例子:
def func(a,b):
return a*b
s = func(‘knock~’,2)
print(s)
输出结果如下:
函数可以没有return,此时函数并不返回值。函数也可以用return返回多个值,多个值以元组类型保存。如下例子:
def func(a,b):
return b,a
s = func(“knock~”,2)
print(s,type(s))
输出结果如下:
一个程序中的变量包括两大类:全局变量和局部变量。全局变量指在函数之外定义的变量,一般没有缩进,在程序执行全过程有效。局部变量指在函数内部使用的变量,仅在函数内部有效,当函数退出时变量将不存在。下面通过程序给大家区分两者:
n = 1 #n是全局变量
def func(a,b):
c = a * b #c是局部变量,a和b作为函数参数也是局部变量
return c
s = func(“knock~”,2)
print(c)
我们运行上述程序,会出现这样的一个结果:
结果提示变量c未被定义,而我们在func()函数里面已经提前进行了声明。这是因为c是一个局部变量,这个例子也说明了一点:当函数执行完退出后,它内部的变量也会随之释放。那如果说函数内部使用了全局变量呢?它会不会随着函数运行的结束而消失呢?我们通过下面的程序进行一下测试:
n = 1 #n是全局变量
def func(a,b):
n = b #这个n是函数内存中新生成的局部变量,不是全局变量
return a*b
s = func(“knock~”,2)
print(s,n) #测试一下n的值是否发生了改变
运行结果如下:
我们可以发现,n的值依旧是1,它并没有改变为变量参数b的值。这也就说明,在函数内部使用全局变量,在运行结束时全局变量的值并不会因此受到任何影响。事实上,每一个函数,包括我们上面自定义的func()函数,都有着自己的内存空间,即便我们在函数内部用到了全局变量n,函数本身也不会将n认定为全局变量,所以此n非彼n,这里的n依旧只是个局部变量。在函数退出后,局部变量n就会被释放,而这些变化对于全局变量n没有任何的影响。
那如果我们希望在函数内部去调用全局变量呢?这时候我们需要在变量n使用前显式声明该变量为全局变量。下面通过程序来进行说明:
n = 1 #n是全局变量
def func(a,b):
global n
n = b #将局部变量b赋值给全局变量n
return a*b
s = func(“knock~”,2)
print(s,n) #测试一下n的值是否发生了改变
运行结果如下:
我们可以看到,全局变量n的值发生了改变。
上面是关于全局变量是整数的几种情形。那么我们来设想一下,如果全局变量不是整数n,而是列表类型ls,会怎样呢?我们通过代码来测试一下:
ls = [] #ls是全局列表变量
def func(a,b):
ls.append(b) #将局部变量b增加到全局列表变量ls中
return a*b
s = func(“knock~”,2)
print(s,ls) #测试一下ls值是否改变
运行结果如下:
我们发现,与之前的整数变量n不同,全局列表变量在函数func()调用后竟然发生了改变。这个是因为列表的性质所导致的。列表等组合数据类型由于操作多个数据,所以它们在使用中有创建和引用的分别。当列表变量被方括号赋值时,这个列表才被真实创建,否则只是对之前创建列表的一次引用。(详见教案6.2)
如果func()函数内部存在一个真实创建过且名称为ls的列表,则func()函数将操作该列表而不会修改全局变量。程序示例如下:
ls = [] #ls是全局列表变量
def func(a,b):
ls = [] #创建了名称为ls的局部列表变量
ls.append(b) #将局部变量b增加到全局列表变量ls中
return a*b
s = func(“knock~”,2)
print(s,ls) #测试一下ls值是否改变
程序的运行结果如下: