1.什么是函数
函数就是一个可重复调用的工具
2.为什么使用函数
防止代码冗余,代码可读性差
定义函数:关键字(def)函数名(index)括号(函数描述)
调用函数
4.分类
无参函数:def index(): print'ok'
空函数:def login():pass
有参函数:
username = 123
def login(username):print (username)
5.return用法:
什么是return:return是一个函数结束的标志,函数体代码只要执行到return函数执行结束
return用法分类:
不写return:默认返回None
只写return:只有结束函数体代码的效果,返回None
只写return None:与只写return相同,只有结束函数体代码的效果,返回None
return只返回一个值:会将返回的结果当作一个变量来使用
return返回多个值:将返回的多个值默认存入元祖返回
函数的值不想被修改可以将自己指定返回的数据类型
6.函数的参数:
形参:在函数定义阶段就规定的参数,相当于定义变量时的变量名
实参:在函数调用阶段传入的参数,相当于定义变量时的变量值
位置参数:通过位置进行传参
关键字参数:以键值对形式的参数称之为关键字参数
PS:位置参数要写在关键字参数的前边,连用时不可对同一个参数重复赋值
默认参数:在定义函数阶段就已经传的参数,如果在实参的时候传入一个新的参数,就会使用新的参数
def foo(n, arg=None):
if arg is None:
arg = []
arg.append(n)
return arg
print(foo(3))
可变长参数:
在调用函数时,实参的个数可以不固定。而在调用函数时,实参的定义无非是按位置或者关键字两种形式,这就要求形参提供两种解决方案分别处理两种形式的可变长度的参数。
1.可变长参数中的位置参数
如果在最后一个形参名前加*号,那么在调用函数时,溢出的位置参数,都会被接受,以元祖的形式保存下来赋值给该形参
def foo(x,y,z,*args):
print(x,y,z)
print(args)
foo(1,2,3,4,5,6)
def foo(x,y,z,*args):
print(x,y,z,args)
l =[1,2,3]
foo(1,2,*l)
1 2 1 (2, 3)
2.可变长度的关键字参数
如果在最后一个形参名前加**号那么在调用函数时,溢出的关键字会被接收,以字典的形式保存下来赋值给该形参
def a (x,y,**kwargs):
print(x)
print(y)
print(kwargs)
l = {'b':1,'c':2}
a(1,2,**l)
2.6命名关键字参数,函数调用者就可以传入任意的关键字参数key=value,如果函数代码的执行需要依赖某个key,必须在函数内判断。
>>> def register(name,age,**kwargs):
... if 'sex' in kwargs:
... #有sex参数
... pass
... if 'height' in kwargs:
... #有height参数
... pass
...
想要限定函数的调用者必须以key=value的形式传值,Python3提供了专门的语法:需要在定义形参时,用作为一个分隔符号,号之后的形参称为命名关键字参数。对于这类参数,在函数调用时,必须按照key=value的形式为其传值,且必须被传值
>>> def register(name,age,*,sex,height): #sex,height为命名关键字参数
... pass
...
>>> register('lili',18,sex='male',height='1.8m') #正确使用
>>> register('lili',18,'male','1.8m') # TypeError:未使用关键字的形式为sex和height传值
>>> register('lili',18,height='1.8m') # TypeError没有为命名关键字参数height传值。
命名关键字参数也可以有默认值,从而简化调用
>>> def register(name,age,*,sex='male',height):
... print('Name:%s,Age:%s,Sex:%s,Height:%s' %(name,age,sex,height))
...
>>> register('lili',18,height='1.8m')
Name:lili,Age:18,Sex:male,Height:1.8m
需要强调的是:sex不是默认参数,height也不是位置参数,因为二者均在后,所以都是命名关键字参数,形参sex=’male’属于命名关键字参数的默认值,因而即便是放到形参height之前也不会有问题。另外,如果形参中已经有一个args了,命名关键字参数就不再需要一个单独的*作为分隔符号了
>>> def register(name,age,*args,sex='male',height):
... print('Name:%s,Age:%s,Args:%s,Sex:%s,Height:%s' %(name,age,args,sex,height))
...
>>> register('lili',18,1,2,3,height='1.8m') #sex与height仍为命名关键字参数
Name:lili,Age:18,Args:(1, 2, 3),Sex:male,Height:1.8m
2.6 组合使用
综上所述所有参数可任意组合使用,但定义顺序必须是:位置参数、默认参数、*args、命名关键字参数、**kwargs
可变参数args与关键字参数**kwargs通常是组合在一起使用的,如果一个函数的形参为args与**kwargs,那么代表该函数可以接收任何形式、任意长度的参数
>>> def wrapper(*args,**kwargs):
... pass
...
在该函数内部还可以把接收到的参数传给另外一个函数(这在4.6小节装饰器的实现中大有用处)
>>> def func(x,y,z): ... print(x,y,z) ... >>> def wrapper(*args,**kwargs): ... func(*args,**kwargs) ... >>> wrapper(1,z=3,y=2) 1 2 3
按照上述写法,在为函数wrapper传参时,其实遵循的是函数func的参数规则,调用函数wrapper的过程分析如下:
-
位置实参1被*接收,以元组的形式保存下来,赋值给args,即args=(1,),关键字实参z=3,y=2被**接收,以字典的形式保存下来,赋值给kwargs,即kwargs={'y': 2, 'z': 3}
-
执行func(args,kwargs),即func(*(1,),** {'y': 2, 'z': 3}),等同于func(1,z=3,y=2)
提示: *args、**kwargs中的args和kwargs被替换成其他名字并无语法错误,但使用args、kwargs是约定俗成的。