纸上得来终觉浅,绝知此事要躬行!
目录
参数传递概念
给函数传递参数(argument)时,
- 参数的传递是通过自动将对象赋值给本地变量名来实现的。
- 在函数内部的参数名的赋值不会影响调用者。
- 改变函数的可变对象参数的值也许会对调用者有影响。
不可变参数“通过值”进行传递。像整数和字符串这样的对象是通过对象引用而不是拷贝进行传递的,但是对象不可变,看起来就像创建了一份拷贝。
可变对象是通过“指针”进行传递的。可变对象能够在函数内部进行原处的改变,这点和C数组很像。
python内部是使用以下的步骤来在赋值前进行参数匹配的:
- 通过位置分配非关键字参数。
- 通过匹配变量名分配关键字参数。
- 其它额外的非关键字参数分配到*name元组中。
- 其它额外的关键字参数分配到**name字典中。
- 用默认值分配给在头部未得到分配的参数。
关键字参数&默认参数
当关键字参数在调用过程中使用时,参数排列的位置并没有关系,Python通过变量名进行匹配,而不是位置。
def f(a,b,c):print(a,b,c)
f(1,2,3)
# 1,2,3
f(a=1,b=3,c=2)
# 1,3,2
f(1,c=3,b=2)
# 1,2,3
def f(a,b=2,c=3):print(a,b,c)
f(1)
# 1,2,3
f(1,2,2)
# 1,2,2
任意参数
*和**是让函数支持任意数目的参数的。
*:在元组中收集不匹配的位置参数,Python将所有位置相关的参数收集到一个新的元组中,并将这个元组赋值非变量。
**:只对关键字参数有效,将这些关键字参数传递给一个新的字典,这个字典之后将能够通过一般的字典工具进行处理。
def g(*args):print(args)
g()
# ()
g(3)
# (3,)
g(3,21,5)
# (3, 21, 5)
def h(**args):print(agrs)
h()
# {}
h(1,2)
'''
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-17-19bdbe2b3953> in <module>()
----> 1 h(1,2)
TypeError: h() takes 0 positional arguments but 2 were given
'''
h(a="lin",b="yue")
# {'a': 'lin', 'b': 'yue'}
def k(a,*pargs,**kargs):print(a,pargs,kargs)
k(1,3,2,"lin",c="lin",b="yue")
# 1 (3, 2, 'lin') {'c': 'lin', 'b': 'yue'}
在最新Python版本中,可以在调用函数时使用*和**语法,与函数定义的意思相反,“解包参数”。
def func(a,b,c,d):print(a,b,c,d)
func(*(1,2),**{"d":4,"c":7})
# 1 2 7 4
func(1,*(2,3),**{"d":5})
# 1 2 3 5
Keyword-Only参数
Py3把函数头部的排序规则通用化,允许我们指定Keyword-only参数:必须只按照关键字传递并且不会由一个位置参数来填充的参数。keyword-only参数编码为命名的参数,出现在参数列表中的*args之后,且不能出现在**args任意关键字形式之后。