函数的参数是参数暴露给外部的接口,向函数传递参数,能够控制函数的流程,函数能够0个、1个或多个参数;在Python中向函数传参,使用的是赋值方式。express
一,传递参数
参数是经过赋值来传递的,传递参数的特色是:app
- 参数的传递是经过自动把对象赋值给函数的本地变量名来实现的,
- 在函数内部的变量名的赋值不会影响调用者,在函数运行时,在函数头部的参数名是一个新的、本地的变量名,这个变量名的做用域是在函数的本地做用域内。
- 改变函数的可变对象参数的值,会修改原始对象的值。
当经过赋值方式,把可变对象的引用传递给函数时,在函数内部对参数进行修改,在函数外部能够看到修改。函数
例如,列表是一个可变对象,当把列表 a 传递给 changer函数时,函数向列表末尾添加一个字符a,当函数调用结束时,列表末尾被修改。编码
>>> def changer(x): ... x.append('a') ... >>> a=[1,2,3] >>> changer(a) >>> a [1, 2, 3, 'a']
这是因为可变对象是经过指针进行传递的,当把列表的引用传递给参数时,函数直接在原处修改对象。spa
也能够经过向参数传递拷贝的方式,使得函数没法修改原始的对象。指针
changer(a[:]) changer(a.copy())
二,参数匹配模型
无论使用何种参数的匹配模型,参数老是经过赋值进行传递的。code
在默认状况下,参数是经过其位置进行匹配的,从左向右,并且必须精确地传递和函数头部参数名同样多的参数。还可以经过参数名匹配,默认参数名,以及对于额外参数的容器来进行传参。对象
1,位置匹配blog
通常状况下,参数是经过位置从左至右进行匹配,把参数传递给函数头部的参数名称。接口
例如,定义函数func,包含三个参数,那么必须使用三个参数传值进行调用:
def func(a,b,c):
调用的格式是,按照顺序把值写在括号中,Python按照位置匹配参数,把1赋值给a,把2赋值给b,把3赋值给c:
func(1,2,3)
2,关键字匹配
调用者使用arg_name=value的方式,经过在调用时使用参数的变量名进行匹配。
例如,定义参数func,包含三个参数,那么必须使用三个参数传值进行调用:
def func(x,y,z):
使用关键字调用的格式是:按照 arg=named的方式进行匹配,能够不按照位置:
func(y=2, x=1, z=3)
在调用函数时,Python按照参数名进行匹配,把2传递给参数y,把1传递给参数x,把3传递给参数z。
也能够混合使用位置匹配和关键字匹配,例如,下面的函数调用:
func(1,z=3,y=2)
基于位置的匹配参数,首先按照从左至右的顺序匹配前面的参数,以后,再按照基于变量名进行关键字匹配。
3,默认参数
在定义函数时,能够为函数的参数赋值,这就是参数的默认值。当没有为该参数传值时,参数值使用默认值。
例如,定义一个函数,包含三个参数,x、y和z,其中参数z有默认值1:
def func(x,y,z=1):
当调用这个函数,必须为参数x和y传值,不管是经过位置匹配仍是关键字匹配来实现均可以。然而,参数z的传值是可选的。若是不为z传值,那么z使用默认值;若是为z传值,那么z使用传递的值。
func(2,3)
4,可变长参数列表
可变参数用于收集任意多个基于位置或关键字的参数,在函数定义时,若是参数名前带一个*号,那么该参数收集的是基于位置的传值;若是参数名前带两个*号(**arg),那么该参数收集的是基于关键字(arg=value)的传值。
def func(*args) def func(**dict)
这两种方式的不一样点是,*args方式是把任意多个传值封装成元组(arg1,arg2),而**dict是把任意多个 arg=value 封装成字典{arg:value},字典的key是参数名,字典key对应的值是参数的值。
例如,定义函数foo,包含一个位置匹配参数,1个可变的位置匹配参数,1个可变的关键字匹配参数:
def foo(a,*b,**c):
在调用函数时,首先按照位置匹配,把1传递给参数a,把元组(2,3)传递给参数b,把字典{x:1,y:2}传递给参数c:
foo(1,2,3,x=1,y=2)
5,只能使用关键字参数
参数必须按照名称传值,在函数定义时,参数必须在调用中按照关键字进行传值:
def func(*,arg=value)
从语法上来说,keyword-only参数编码为关键字参数,出如今参数列表的*args以后,全部这些参数都必须在调用中使用关键字语法来传值。
def foo(a,*b,c):
在调用foo函数时,参数a能够按照位置和关键字来传值,参数b接收按照其他的按照位置来传值的变量,参数c必须按照关键字来传值:
foo(1,2,'a',3,c='key')
也能够在参数列表中使用一个*字符,来表示一个函数不会接受一个可变的参数列表,而是仍然期待跟在*后面的全部参数都做为关键字匹配。
例如,定义函数foo,只接受3个参数,不接受可变长度的参数列表:
def foo(a,*,b,c):
在调用时,参数a能够按照位置和关键字来传值,参数b和c必须按照关键字来传值:
foo(1,b='x',c=2)
三,lambda表达式
除了def语句以外,Python还提供了一种生成函数对象的表达式形式,lambda表达式。就像def语句同样,这个表达式建立了一个函数对象,可是它返回了一个函数,而不是把这个函数赋值给一个变量名。
lambda表达式的通常形式是关键字lambda,以后是一个或多个参数(与一个def头部内用括号括起来的参数列表极其相似),紧跟一个冒号,以后是一个表达式:
lambda arg1,arg2,... argN: expression_using_args
lambda表达式的特性是:
- lambda表达式返回的是函数对象;
- lambda是一个表达式,而不是一个语句,做为一个表达式,lambda返回了一个值(一个新的函数),能够选择性地赋值给一个变量名;
- lambda的主体是一个单个的表达式,而不是一个代码块,这个表达式的结果做为函数的结果返回。
lambda只有一行表达式,只能用于建立简单的函数,而def 能够包含多条语句,用于处理复杂的任务。
对于简单的处理流程,既能够使用def,也能够用lambda来实现,例如:
def func(x,y,z): return x+y+z func=lambda x,y,z: x+y+z
因为lambda表达式返回的是一个函数对象,所以,能够用于map()、filter()和reduce()函数中:
list(map((lambda x: x+3), range(0,5))) list(filter((lambda x: x>2), range(0,5))) from functools import reduce reduce((lambda x,y: x+y),range(0,5))
reduce()函数对每对元素都应用函数,并运行到最后结果,上述reduce()函数的做用是把序列中的全部元素相加,等价的写法是:
x=list(range(0,5)] res=x[0] for i in x[1:] : res+=i
四,函数的属性
能够向函数添加任意多个用户定义的属性,函数属性的格式是:函数名称.变量名
例如,向函数func中添加state属性:
def func(): func.state='begin'
参考文档: