[toc] 本片文章主要整合15. 函数和装饰器和python的可变参数和关键字参数(*args **kw)两篇文章,并做对比总结,以及添加综合案例。主要目标是熟悉 python 中函数传参种类和方法,并掌握不同传参的优缺点和联合传参的注意事项。 本文难免有不足之处,若对该主题感兴趣,如下的几个参考文献可能帮助到你
| 种类 | 函数定义 | 参数传递 | 功能 | 参考 |
|---|---|---|---|---|
| POSITIONAL_ONLY 位置参数 | ord(c, /) | 一些内置函数,只支持位置传入 | 1.1 POSITIONAL_ONLY 位置参数 | |
| POSITIONAL_OR_KEYWORD 位置或关键字参数 | def foo(n): | 自定义函数支持位置和关键字传入,这种类型最常见 | 基础传入方式,最常用 | |
| VAR_POSITIONAL 可变长参数 | def variable_args(name="default", *args): | 1. 传入列表 list<br />2. 传入元组 tuple<br /> 3. 传入逐个传入元素 | 降低变长数组和元组传入的复杂度 | 2.1 VAR_POSITIONAL 可变长参数 参数传递 |
| KEYWORD_ONLY 关键字参数 | def person(name, age, *, city, job): | 1. city 和 job 通过关键字传入 | 限制输入的关键字参数 | 2.3命名关键字参数 |
| VAR_KEYWORD 可变关键字参数 | def person(name, age, **kw) | 1. 关键字传入<br />2. 传入字典 dict | 任意不受限,但是函数内部要增加检查 | 2.3VAR_KEYWORD 可变关键字参数 参数传递 |
定义一个可以处理任意类型任意参数数目的函数。
def test_args(*args, **kwargs):
print(args)
print(kwargs)
test_args(1, 2, {"key0": "val0"}, name="name", age=18)
>>>
(1, 2, {'key0': 'val0'})
{'name': 'name', 'age': 18}
test_args() 是一个可以接受任意多个参数的函数。由于参数处理是有优先级的,kwargs 和 args 顺序不可颠倒。
def f1(a, b, c=0, *args, **kw):
print('a =', a, 'b =', b, 'c =', c, 'args =', args, 'kw =', kw)
def f2(a, b, c=0, *, d, **kw):
print('a =', a, 'b =', b, 'c =', c, 'd =', d, 'kw =', kw)
>>> f1(1, 2)
a = 1 b = 2 c = 0 args = () kw = {}
>>> f1(1, 2, c=3)
a = 1 b = 2 c = 3 args = () kw = {}
>>> f1(1, 2, 3, 'a', 'b')
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {}
>>> f1(1, 2, 3, 'a', 'b', x=99)
a = 1 b = 2 c = 3 args = ('a', 'b') kw = {'x': 99}
>>> f2(1, 2, d=99, ext=None)
a = 1 b = 2 c = 0 d = 99 kw = {'ext': None}
>>> args = (1, 2, 3, 4)
>>> kw = {'d': 99, 'x': '#'}
>>> f1(*args, **kw)
a = 1 b = 2 c = 3 args = () kw = {'d': 99, 'x': '#'}
>>> args = (1, 2, 3)
>>> kw = {'d': 88, 'x': '#'}
>>> f2(*args, **kw)
a = 1 b = 2 c = 3 d = 88 kw = {'x': '#'}
Python 中的函数参数类型一共有五种,参考 inspect 模块 ,分别是: