Python函数参数
- 在代码中定义一个名称的位置决定了它大部分的含义
- 函数的参数就是对象作为输入发送给函数的方式。
传递参数
- 参数的传递是通过自动将对象赋值给本地变量名来实现的。函数参数引用是以指针的形式实现的,所有的参数实际上都是通过指针进行传递的。作为参数被传递的对象从来不自动拷贝
- 在函数内部的参数名的赋值不会影响调用者,在函数中,在函数头部的参数名是一个新的、本地的变量名,这个变量名时在函数的本地作用域内的。
- 改变函数的可变对象参数的值,对于就地改变的对象会影响调用者
- 不可变参数“通过值”进行传递。像整数和字符串这样的对象是通过引用而不是拷贝进行传递。实际的效果就像创建了一份拷贝
- 可变对象是通过"指针"进行传递的。例如 列表和字典
特定的参数匹配
- 在默认情况下,参数是通过位置进行匹配的,从左至右,而且必须精确地传递和函数头部参数名一样多的参数
def f(a,b,c):print(a,b,c)
通过参数名进行匹配
- 调用者可以定义哪一个函数接受这个值,通过在调用时使用参数的变量名,使用name=value这种语法,如果调用时传入的值过于少的话,函数能够为参数定义接受的默认值,使用name=value
f(a=1,b=2,c=3)
f(1,c=3,b=2)
参数默认值
def f(a,b=2,c=3):print(a,b,c)
- 上面函数定义中,必须为a提供值,无论是通过位置参数还是关键字参数。然而b和c提供值时可选的。如果我们不给b和c传递值他们会默认按照默认参数为参数赋值。
>>> def f(a,b=1,c=2):
... print(a,b,c)
...
>>> f(1)
1 1 2
>>> f(1,2)
1 2 2
>>> f(1,2,5)
1 2 5
可变参数:收集任意多基于位置或关键字的参数
函数能够使用特定的参数,这些参数以字符*开头
可变参数解包:传递任意多的基于位置或关键字的参数
调用者能够再使用*语法去将参数集合打散,分成参数。*在函数头部表示函数接收任意多的参数,而在调用者中意味着传递任意多的参数
def f(*args):print(args)
当这个函数调用,Python将所有位置相关的参数收集到一个新的元组中,并将这个元组赋值给变量args。
>>> def ff(*args):
... print(args)
>>> ff()
()
>>> ff(1,2,3,4)
(1, 2, 3, 4)
- 在函数的调用中,使用name=value的形式告诉Python依照变量名进行匹配,这叫做关键字参数,在调用中使用sequence或者*dict允许我们在一个序列或字典中相应的封装任意多的位置相关或者关键字的对象。并在将他们传递给函数的受,将他们解包为分开的单个的参数
- 在函数的头部,一个简单的变量名是通过位置或变量名进行匹配的,但是name=value的形式定义了默认的参数值。name的形式收集了任意的额外不匹配的参数到元组中,并且name的形式将会收集额外的关键字参数到字典中,在python3.0及其以后的版本中,跟在name或一个*之后的,任何正式的或默认的参数名称都是keyword-only参数,并且必须在调用中按照关键字传递
>>> def fff(**args):print(args)
>>> fff(a=1,b=2)
{'a': 1, 'b': 2}
# 混合调用
>>> def ffff(a,*b,**c):print(a,b,c)
>>> ffff(1,2,3,4,x=2,y=3)
1 (2, 3, 4) {'x': 2, 'y': 3}
Keyword-only:参数必须按照名称传递
在Python3.0中,函数可以指定参数,参数必须用带有关键参数的名字来传递。这样的参数通常用来定义实际参数
特定参数匹配模式语法
解包参数
最新的Python版本中,我们在调用函数时可以使用*语法,这种情况下,它与函数定义的意思相反。它会解包参数集合。不是创建参数集合
>>> def func(a,b,c,d):
... print(a,b,c,d)
...
>>> args = (1,2)
>>> args+=(3,4)
>>> func(*args)
1 2 3 4
"**"会以键值对的形式解包一个字典,解包后会成为独立的关键字参数
>>> def func(a,b,c,d):
... print(a,b,c,d)
>>> args={'a':1,'b':2,'c':'sdasd','d':3333}
>>> args['d']=2222
>>> func(**args)
1 2 sdasd 2222
细节
使用并混合特定的参数匹配模型,Python将会遵循如下法则:
- 在函数调用中,参数必须以此顺序出现:任何位置参数(value)、后面跟着任何关键字参数(name=value)和sequence形式的组合,后面跟着*dict形式
- 在函数头部,参数必须以此顺序出现:任何一般参数(name),紧跟着任何默认参数(name=value),后面是name(Python3.0中是)形式,后面跟着任何name或name=value keyword-only参数,后面跟着**name形式
- 在调用和函数头部中,如果出现**arg形式的话,必须出现在最后。
- 当关键字参数在调用过程中使用时,参数排列的位置没有关系。Python通过变量名进行匹配,而不是位置。
Python内部是使用以下步骤来在赋值前进行参数匹配的:
1.通过位置分配非关键字参数
2.通过匹配变量名分配关键字参数
3.其他额外的非关键字参数分配到name元组中。
4.其他额外的关键字参数分配到*name字典中
5.用默认值分配给在头部未得到分配的参数
然后Python检测来确保每个参数只传入了一个值。所有匹配完成后,Python会把传递给参数名的对象赋值