Python函数参数类型与注解详解:定位、可变、默认及关键字参数
本文深入解析Python函数的四种核心参数类型:定位参数、*args可变参数、默认值参数及**kwargs关键字参数,并重点讲解Python3新增的仅限关键字参数定义规则。同时介绍如何利用__defaults__、__kwdefaults__及inspect库进行函数内省,以及使用类型注解提升代码可读性与IDE支持。
四种参数
Python函数func定义如下:
def func(first, *args, second="Hello World", **kwargs):
print(first)
print(args)
print(second)
print(kwargs)
func("dongfanger", "san", py="good")
运行后会输出:
dongfanger
('san',)
Hello World
{'py': 'good'}
它包含四种不同的参数类型:
- first是定位参数(positional parameter),调用时不可省略。
- *args是可变位置参数(arguments),接收到的额外位置参数会被存入元组。
- second是默认值参数(default argument values),调用时可以省略,使用预设值。
- **kwargs是关键字参数(keyword arguments),接收到的额外关键字参数会被存入字典。
func函数的调用方式包含以下几种情况:
①仅传入单个定位参数。
func("dongfanger")
dongfanger
()
Hello World
{}
②第一个参数后的任意数量位置参数会被*args捕获,并打包为一个元组。
func("dongfanger", "a", "b", "c")
dongfanger
('a', 'b', 'c')
Hello World
{}
③未明确指定名称的关键字参数会被**kwargs捕获,并打包为一个字典。
func("dongfanger", j="1", k="2")
dongfanger
()
Hello World
{'j': '1', 'k': '2'}
④second参数只能以关键字参数的形式传入。
func("dongfanger", second="cool")
dongfanger
()
cool
{}
⑤定位参数也可以显式地作为关键字参数传入。
func(first="san")
san
()
Hello World
{}
⑥若字典前加上**,其所有键值对将作为单个参数传入,同名键会绑定到对应的具名参数上,剩余未匹配的键值对则被**kwargs捕获。
my_dict = {"first": "dongfanger", "location": "cd", "second": "cool", "age": "secret"}
func(**my_dict)
dongfanger
()
cool
{'location': 'cd', 'age': 'secret'}
除了上述四种参数,Python3还引入了一种仅限关键字参数(keyword-only argument)。
仅限关键字参数
仅限关键字参数是Python3的新特性。在func函数中,second参数即为仅限关键字参数,“仅限”意味着它只能通过关键字形式指定,绝不会捕获未命名的定位参数。
若调整参数位置定义another_func函数:
def another_func(first, another_second="Hello World", *args, **kwargs):
print(first)
print(another_second)
print(args)
print(kwargs)
another_func("dongfanger", "a", "b", "c")
输出结果将变为:
dongfanger
a # 注意这里
('b', 'c')
{}
此时another_second不再是仅限关键字参数,而退化为普通的默认值参数,因为它成功捕获到了定位参数。
由此可见,定义仅限关键字参数必须将其放置在*args之后,如func函数所示;反例即another_func函数。
另一种定义仅限关键字参数的方法是在签名中显式放置一个*:
>>> def f(a, *, b): # b是仅限关键字参数
... return a, b
...
>>> f(1, b=2) # 只能传关键字参数
(1, 2)
>>> f(1, 2) # 不能传定位参数
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: f() takes 1 positional argument but 2 were given
>>> f(1, 2, 3) # 不能传定位参数
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: f() takes 1 positional argument but 3 were given
仅限关键字参数不一定需要默认值,例如参数b,若未提供默认值,则强制要求调用时必须传入实参。
内省中的函数参数
函数内省指的是当获取到一个“函数对象”时,可以进一步查询其名称、参数定义等元信息。这些信息可通过函数对象的属性(即双下划线开头的魔法方法)获取。
对于func函数:
def func(first, *args, second="Hello World", **kwargs):
print(first)
print(second)
print(args)
print(kwargs)
以及another_func函数:
def another_func(first, another_second="Hello World", *args, **kwargs):
print(first)
print(another_second)
print(args)
print(kwargs)
【__defaults__属性】
该属性为元组,保存着定位参数和默认值参数的默认值。
print(func.__defaults__) # None
print(another_func.__defaults__) # ('Hello World',)
【__kwdefaults__属性】
该属性为字典,保存仅限关键字参数的默认值。
print(func.__kwdefaults__) # {'second': 'Hello World'}
print(another_func.__kwdefaults__) # None
【__code__属性】
该属性引用code对象,code对象自身包含多个属性,其中包括参数名称列表。
print(func.__code__.co_varnames) # ('first', 'second', 'args', 'kwargs')
print(another_func.__code__.co_varnames) # ('first', 'another_second', 'args', 'kwargs')
此外,还可以使用inspect库的signature方法来查看内省中的函数参数:
from inspect import signature
print(signature(func))
# (first, *args, second='Hello World', **kwargs)
框架和IDE等开发工具可以利用这些信息进行代码验证和智能提示。
函数注解
如果熟悉力扣算法题,对函数注解应不陌生。例如:
def clip(text:str, max_len:'int > 0'=80) -> str:
pass
参数名后的表达式为注解表达式,用于标注参数类型或约束条件。若参数存在默认值,注解需放置在参数名与=号之间。
可在函数定义末尾的)和:之间添加->及注解表达式,以对返回值类型进行注解。
注解表达式可以是任意类型,最常用的是类(如str或int)或字符串(如'int > 0')。
函数注解仅作为元数据存储,Python对注解的唯一处理是将其存入函数的__annotations__属性中:
print(clip.__annotations__)
#{'text': <class 'str'>, 'max_len': 'int > 0', 'return': <class 'str'>}
Python解释器不会检查、强制或验证注解,不做任何运行时操作!注解仅作为元数据供框架和IDE等工具使用。
以上就是Python函数参数和注解的使用的详细内容,更多关于Python函数参数和注解的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









