位置参数
又叫顺序参数,在未指定参数名时,必须严格按照顺序来传递参数!(很简单)
默认参数
在函数定义的时候,如果给某个参数提供一个默认值,这个参数就变成了默认参数,不再是位置参数了。在调用函数时,既可以给默认参数传递一个自定义的值,也可以使用默认的值
默认参数必须定义在位置参数的后面
重点,默认参数默认值为
None
的情况
先看一个例子:
1 | # 测试 |
为什么会这样?
因为
Python
函数体在被读入内存的时候,默认参数a
指向的空列表对象就会被创建,并放在内存里了。因为默认参数a
本身也是一个变量,保存了指向对象[]
的地址。每次调用该函数,就往指向a
的列表里添加一个A
。a
是没有变的,它始终保存着指向列表的地址,变的是列表内的数据!详细测试请移步博客:刘江的博客:默认参数设置为 None 的情况
若想要输出:
1 | ['A'] |
则代码可以改为:
1 | def func(a=None): |
动态参数
传入参数的个数是动态的(即数量不固定的),可以是
0
个、 1
个、 2
个、
更多个
甚至 任意个
,在不需要的时候,完全可以将动态参数当作空气而忽略它的存在。
Python
中的动态参数有两种,分别是 *args
和
**kwargs
,这里的关键是一个星号 *
和两个星号
**
的区别,而不是 args
和 kwargs
在名字上的区别,实际上可以使用 *any
或
**whatever
的任何命名方式,但就如 self
一样,使用 *args
和 **kwagrs
已经形成了一种不成文的规定,我们应当(最好)遵守它
*args
的作用
将传入的实际参数转换(打包)成一个元组后再传递给形式参数(一个列表当作一个参数)
1 | # 测试 |
可以很清晰地看到, args
的值是一个元组。接下来看看其中
*
的作用:
1 | # 测试 |
至此,已经发现, *args
作为形参,其中起作用的就是
*
号(就像前面说的, args
可以换为任何其它字符串,但我们最好遵守这种命名习惯),它起到打包和解包的作用
既然 *
可以起到解包的作用,那么对于可迭代对象(如字符串、元组、列表)自然便可以起到拆分的效果(但只能拆分
1
层)
1 | # 测试 |
**kwargs
的作用
将传入的实际参数(键-值对参数)转换(打包)成一个字典后再传递给形式参数
1 | # 测试 |
同样地,查看 **
的功能(几乎同 *
理,故以下只进行简单测试):
1 | # 测试 |
注意:直接使用 A, B, C = **{'A': 1, 'B': 2, 'C': 3}
或
print(**{'A': 1, 'B': 2, 'C': 3})
是错误的!
*
和 **
只有在传参时才起作用,即使
print(*(1, 2, 3))
有效,但
a, b, c = *(1, 2, 3)
是无效的!
- 混合参数、万能参数
*args
+**kwargs
的作用
要注意一点,
*args
必须写在**kwargs
的前面当位置参数、默认参数、动态参数混合使用时,要注意默认参数是否被动态参数赋值!