简介

在 Python 中,参数传递方式有两种主要形式:位置参数关键字参数。通过使用包裹传递(packing)和解包传递(unpacking),可以灵活地处理任意数量的参数。

单星号 *

单星号 * 用于处理位置参数的打包和解包。

单星号打包

单星号 * 打包会将多个位置参数打包成一个 tuple 对象

1
2
3
4
5
6
def sum_all(*args):
print(f"{args = }, {type(args) = }")
return sum(args)

result = sum_all(1, 2, 3, 4)
# args = (1, 2, 3, 4), type(args) = <class 'tuple'>

单星号解包

单星号 * 解包用于将一个可迭代对象解包为位置参数

1
2
3
4
5
6
def add(a, b, c):
return a + b + c

data = [1, 2, 3]
print(*data) # 1 2 3
result = add(*data) # add(1, 2, 3)

双星号 **

双星号 ** 用于关键字参数的打包和解包

双星号打包

双星号 ** 打包会将多个关键字参数打包成一个 dict 对象

1
2
3
4
5
6
7
8
9
10
11
def print_info(**kwargs):
print(f"{kwargs = }\n{type(kwargs) = }")
for key, value in kwargs.items():
print(f"{key} = {value}")

print_info(name="Alice", age=30, city="New York")
# kwargs = {'name': 'Alice', 'age': 30, 'city': 'New York'}
# type(kwargs) = <class 'dict'>
# name = Alice
# age = 30
# city = New York

双星号解包

双星号 * 解包用于将一个 dict 对象解包为关键字参数

1
2
3
4
5
6
def information(name, age, city):
print(f"{name = }, {age = }, {city = }")

data = {"name": "Alice", "age": 30, "city": "New York"}
information(**data)
# name = 'Alice', age = 30, city = 'New York'

混合使用 * 和 **

既有位置参数,又有关键字参数时,*args 必须作为位置参数的结尾,或者说 *args 之后的参数都必须是关键字参数。**kwargs 也必须作为关键字参数的结尾。

1
2
3
4
5
6
7
8
9
10
11
def func(a, b, *args, c=10, **kwargs):
print(f"Positional Arguments: {a = }, {b = }")
print(f"Optional Positional Arguments: {args = }")
print(f"Keyword Arguments: {c = }")
print(f"Optional Keyword Arguments: {kwargs = }")

func(1, 2, 3, 4, 5, c=20, d=30, e=40)
# Positional Arguments: a = 1, b = 2
# Optional Positional Arguments: args = (3, 4, 5)
# Keyword Arguments: c = 20
# Optional Keyword Arguments: kwargs = {'d': 30, 'e': 40}

keyword-only arguments

在 Python 中,函数参数列表中如果出现单独的单星号 * 而不是 *args,这种用法的作用是强制要求后面的参数必须以关键字参数的形式传递。这种用法被称为 keyword-only arguments。

1
2
3
4
5
6
7
8
9
def func(a, b, *, c, d):
print(f"a = {a}, b = {b}, c = {c}, d = {d}")

# 正确调用
func(1, 2, c=3, d=4)

# 错误调用
func(1, 2, 3, 4)
# TypeError: func() takes 2 positional arguments but 4 were given