函数的返回值和参数
函数的定义
在Python中,用关键字def关键字来定义函数,如下:
def greet_hello(): print("hello!") greet_hello()
关键字def后面是函数名, 它其实就是一个标识符。后面的括号必须有,里面可以有参数。函数定义,只是声明了一个函数,它不会被执行,需要调用,函数的调用很简单,直接函数名加括号就调用了。定义需要在调用前,也就是说调用时,已经被定义过了,否则抛NameError异常
函数的作用
- 功能封装,便于后面复用。
- 减少冗余代码。
- 代码更易读。
函数的返回值
函数的返回值一般有四种情况:
- 没有返回值,默认会返回None。
- 直接一个return,默认返回None。
- 返回一个值。
- 返回多个值,返回多个值其实也相当于返回一个,返回的多个值用元组接收。可以返回任意数据类型的值。
返回一个值
def mylen(s1): """计算s1的长度""" length = 0 for i in s1: length = length+1 return length #函数调用 str_len = mylen("abc") print('str_len : %s'%str_len)
结果为3
返回多个值
def ret_demo1(): '''返回多个值''' return 1,2,3,4 def ret_demo2(): '''返回多个任意类型的值''' return 1,['a','b'],3,4 ret1 = ret_demo1() print(ret1) ret2 = ret_demo2() print(ret2)
结果为:
(1, 2, 3, 4) (1, ['a', 'b'], 3, 4)
应当注意的是,函数执行时,一旦遇到return,就会结束整个函数。
def ret_demo(): print(111) return print(222) ret = ret_demo() print(ret) 结果为1111 None
可以看到,后面return后面的语句没有执行了。
函数的参数
参数分为形参和实参,函数定义时为形参,函数调用时为实参。参数调用时传入的参数要和定义的个数相匹配(可变参数例外)
传递多个参数
def mymax(x,y): the_max = x if x > y else y return the_max ma = mymax(10,20) print(ma)
结果:20
位置实参
位置参数也就是按照参数定义顺序传入实参,传入的实参个数需要和定义的形参个数匹配。比如def f(x, y, z) 调用使用 f(1, 3, 5) ,此时是一一对应的。
关键字实参
def f(x, y, z) 调用使用 f(x=1, y=3, z=5) ,使用形参的名字来出入实参的方式,如果使用了形参名字,那么传参顺序就可和定义顺序不同。
位置实参和关键字实参混合
应当注意,位置参数必须在关键字参数的前面,同时,对于一个形参只能赋值一次。
def mymax(x,y): #此时x = 10,y = 20 print(x,y) the_max = x if x > y else y return the_max ma = mymax(10,y = 20) print(ma)
默认值参数
默认值参数也就是在定义的时候,给参数一个默认值,也叫缺省值。参数的默认值可以在未传入足够的实参的时候,对没有给定的参数赋值为默认值。默认值参数必须要在后面,不然会报错。
给他们传参的时候跟上面的关键字和默认值传参规则一样。
应该注意的是,如果默认值传参的是一个可变数据类型。后期的结果会保留前面的结果。
def defult_param(a,l = []): l.append(a) print(l) defult_param('alex') defult_param('egon')
结果为:
['alex'] ['alex', 'egon']
可变参数
可变参数分为位置参数的可变参数和关键字参数的可变参数。
位置参数的可变参数*
按位置传值多余的参数都由args统一接收,保存成一个元组的形式。
def mysum(*args):
print(args) the_sum = 0 for i in args: the_sum+=i return the_sum the_sum = mysum(1,2,3,4) print(the_sum)
(1, 2, 3, 4) 10
关键字参数的可变参数**
形参前使用**符号,表示可以接收多个关键字参数,收集的实参名称和值组成一个字典 。
def stu_info(**kwargs): print(kwargs) print(kwargs['name'],kwargs['sex']) stu_info(name = 'alex',sex = 'male')
结果为:
{'name': 'alex', 'sex': 'male'} alex male
位置可变参数和关键字可变参数的混合
混合使用参数的时候,可变参数要放到参数列表的最后,普通参数需要放到参数列表前面,位置可变参数需要在关键字可变参数之前。
def fn(x, y, *args, **kwargs): print(x) print(y) print(args) print(kwargs) fn(3,5,7,9,10,a=1,b='python') 3 5 (7, 9, 10) {'a': 1, 'b': 'python'} fn(3,5) 3 5 () {} fn(3,5,7) 3 5 (7,) {} fn(3,5,a=1,b='python') 3 5 () {'a': 1, 'b': 'python'} fn(7,9,y=5,x=3,a=1,b='python') TypeError: fn() got multiple values for argument 'y'
当位置可变参数放在了最前面,后面的普通参数变成了keyword-only参数。
def fn(*args, x, y, **kwargs): print(x) print(y) print(args) print(kwargs) fn(3,5) TypeError: fn() missing 2 required keyword-only arguments: 'x' and 'y' fn(3,5,7) TypeError: fn() missing 2 required keyword-only arguments: 'x' and 'y' fn(3,5,a=1,b='python') TypeError: fn() missing 2 required keyword-only arguments: 'x' and 'y' fn(7,9,y=5,x=3,a=1,b='python') 3 5 (7, 9) {'a': 1, 'b': 'python'}
keyword-only参数
如果在一个星号参数后,或者一个位置可变参数后,出现的普通参数,实际上已经不是普通的参数了,而是keyword-only参数。就像上面的例子一样。而如果是关键字可变参数在前面,像def daf(**kwargs, x)则会直接报语法错误,可以理解为kwargs会截获所有的关键字参数,就算你写了x=5,x也永远得不到这个值,所以语法
错误。
def fn(*, x,y):
*号之后,普通形参都变成了必须给出的keyword-only 参数
print(x,y) fn(x=5,y=6)
可变参数和参数默认值
def fn(*args,x = 5): print(x) print(args) fn()#等价于fn(x=5) 5 () fn(5) 5 (5,) fn(x=6) 6 () fn(1,2,3,x=6) 6 (1, 2, 3)
def fn(y,*args,x=5): print("x={},y={}".format(x,y)) print(args) fn() TypeError: fn() missing 1 required positional argument: 'y' fn(5) x=5,y=5 () fn(x=6) TypeError: fn() missing 1 required positional argument: 'y' fn(1,2,3,x=10) SyntaxError: positional argument follows keyword argument fn(1,2,y=3,x=10) TypeError: fn() got multiple values for argument 'y'
可变参数和关键字可变参数
def fn(x=5,**kwargs): print("x={}".format(x)) print(kwargs) fn() x=5 {} fn(5) x=5 {} fn(x=6) x=6 {} fn(y=3,x=5) x=5 {'y': 3} fn(3,y=10) x=3 {'y': 10}
由此可见,参数列表参数一般顺序是,普通参数、缺省参数、可变位置参数、keyword-only参数(可带缺省值)、可变关键字参数 。
参数解构
给函数提供实参的时候,可以在集合类型前使用*或者**,把集合类型的结构解开,提取出所有元素作为函数的实参 。非字典类型使用*解构成位置参数 ,字典类型使用**解构成关键字参数 。提取出来的元素数目要和参数的要求匹配,也要和参数的类型匹配。
def add(x,y): return x+y add(4,5) 9 add((4,5)) TypeError: add() missing 1 required positional argument: 'y' add(*(4,5)) 9 t=(4,5) add(t[0],t[1]) 9 add(*t) 9 add(*[4,5]) 9 add(*{4,5}) 9 add(*range(1,3)) 3
d = {‘x’: 5, ‘y’: 6}
add(**d)
11
add(**{‘a’: 5, ‘b’: 6})
TypeError: add() got an unexpected keyword argument ‘a’
add(*{‘a’: 5, ‘b’: 6})
‘ab’