位置参数
又叫顺序参数,在未指定参数名时,必须严格按照顺序来传递参数!(很简单)
默认参数
在函数定义的时候,如果给某个参数提供一个默认值,这个参数就变成了默认参数,不再是位置参数了。在调用函数时,既可以给默认参数传递一个自定义的值,也可以使用默认的值
默认参数必须定义在位置参数的后面
重点,默认参数默认值为
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的前面当位置参数、默认参数、动态参数混合使用时,要注意默认参数是否被动态参数赋值!