星号()在Python函数中主要用于参数收集、解包和强制关键字参数。在函数定义时,args将位置参数打包为元组,kwargs将关键字参数打包为字典;在函数调用时,可迭代对象将其元素解包为位置参数,字典将其键值对解包为关键字参数;此外,单独的可作为分隔符,强制其后的参数必须以关键字形式传递,提升代码可读性和API设计清晰度。

在Python函数参数前看到星号(
*
星号(
*
1. 参数收集(Packing)
当你在函数定义时使用一个星号(
*
**
立即学习“Python免费学习笔记(深入)”;
*`args`:收集位置参数**
当你在函数定义中看到
def my_function(*args):
my_function
args
args
*items
例子:
def calculate_sum(*numbers):
print(f"收到的参数类型是:{type(numbers)}")
total = 0
for num in numbers:
total += num
return total
print(calculate_sum(1, 2, 3)) # 输出:收到的参数类型是:<class 'tuple'>, 6
print(calculate_sum(10, 20, 30, 40)) # 输出:收到的参数类型是:<class 'tuple'>, 100
print(calculate_sum()) # 输出:收到的参数类型是:<class 'tuple'>, 0在我看来,这极大地增强了函数的灵活性,尤其是在你不知道调用者会传入多少个参数时,比如一个简单的求和函数或者一个日志记录器。
`kwargs`:收集关键字参数**
类似地,当你在函数定义中看到
def my_function(**kwargs):
kwargs
kwargs
**options
例子:
def display_info(**details):
print(f"收到的参数类型是:{type(details)}")
for key, value in details.items():
print(f"{key}: {value}")
display_info(name="Alice", age=30, city="New York")
# 输出:
# 收到的参数类型是:<class 'dict'>
# name: Alice
# age: 30
# city: New York
display_info(product="Laptop", price=1200)
# 输出:
# 收到的参数类型是:<class 'dict'>
# product: Laptop
# price: 1200这种模式在配置函数或构建灵活的API时非常常见,例如,Django ORM中的
filter()
**kwargs
2. 参数解包(Unpacking)
当你在函数调用时使用一个星号(
*
**
*`iterable`:解包可迭代对象**
如果你有一个列表或元组,并且想将它的每个元素作为独立的参数传递给函数,你可以在变量前加上一个星号。
例子:
def greet(name1, name2, name3):
print(f"Hello {name1}, {name2}, and {name3}!")
names = ["Alice", "Bob", "Charlie"]
greet(*names) # 等同于 greet("Alice", "Bob", "Charlie")
# 输出:Hello Alice, Bob, and Charlie!
# 另一个常见的例子是与内置函数结合
numbers = [10, 20, 5]
print(max(*numbers)) # 等同于 max(10, 20, 5), 输出:20这对于我来说,是代码简洁性的一个巨大提升,避免了手动索引和传递每个元素,特别是在参数数量不固定时。
`dictionary`:解包字典**
如果你有一个字典,并且想将它的键值对作为关键字参数传递给函数,你可以在字典变量前加上两个星号。字典的键会成为参数名,值会成为参数值。
例子:
def configure_printer(model, dpi, color_mode):
print(f"Configuring {model}: DPI={dpi}, Color Mode={color_mode}")
printer_settings = {"model": "HP LaserJet", "dpi": 600, "color_mode": "Grayscale"}
configure_printer(**printer_settings)
# 输出:Configuring HP LaserJet: DPI=600, Color Mode=Grayscale
# 结合参数收集和解包
def create_user(username, email, **profile_data):
print(f"Creating user: {username}, Email: {email}")
for key, value in profile_data.items():
print(f" {key}: {value}")
user_info = {"username": "john_doe", "email": "john@example.com", "age": 30, "city": "London"}
create_user(**user_info) # 注意这里,username和email会被提取,剩下的进入profile_data
# 输出:
# Creating user: john_doe, Email: john@example.com
# age: 30
# city: London这种解包方式在处理配置字典或者将一个函数的结果作为另一个函数的输入时非常方便。
3. 强制关键字参数
在函数定义中,单个星号(
*
*
例子:
def send_email(to, subject, *, body, attachments=None):
print(f"To: {to}")
print(f"Subject: {subject}")
print(f"Body: {body}")
if attachments:
print(f"Attachments: {', '.join(attachments)}")
send_email("user@example.com", "Meeting Reminder", body="Don't forget the meeting!")
# 输出:
# To: user@example.com
# Subject: Meeting Reminder
# Body: Don't forget the meeting!
# send_email("user@example.com", "Meeting Reminder", "Don't forget the meeting!")
# 这会报错:TypeError: send_email() takes 2 positional arguments but 3 were given这种用法在我看来,对于提高代码的可读性和防止调用者误用参数至关重要。它强制调用者明确参数的意图,尤其是在函数有多个参数且某些参数的顺序不那么直观时。
*args
**kwargs
*args
**kwargs
当你在函数签名中看到
*args
*args
args
args
def func(a, b, *args):
func(1, 2, 3, 4, 5)
a
b
args
(3, 4, 5)
类似地,
**kwargs
**kwargs
**kwargs
kwargs
def func(x, **kwargs):
func(10, name="Alice", age=30)
x
kwargs
{'name': 'Alice', 'age': 30}这种工作方式提供了极大的灵活性,尤其是在编写通用工具函数、装饰器或者需要接受各种配置选项的API时。我经常用它们来构建那些可以根据用户需求动态调整行为的函数,而不需要为每种可能的参数组合都定义一个独立的函数签名。这种模式也使得函数对未来的参数扩展更具弹性,因为它允许在不修改现有函数签名的情况下添加新的可选参数。
在函数调用时,星号(
*
**
当你有一个列表或元组,并且其中的元素恰好对应一个函数所需的位置参数时,你可以使用单个星号(
*
my_list = [1, 2, 3]
add(a, b, c)
add(*my_list)
my_list
1, 2, 3
a, b, c
add(my_list[0], my_list[1], my_list[2])
# 示例:解包列表作为位置参数
def describe_person(name, age, city):
print(f"{name} is {age} years old and lives in {city}.")
person_data = ["Jane Doe", 28, "San Francisco"]
describe_person(*person_data)
# 输出:Jane Doe is 28 years old and lives in San Francisco.对于字典,如果你有一个字典,它的键与函数所需的关键字参数名称匹配,那么你可以使用双星号(
**
my_dict = {'x': 10, 'y': 20}draw_point(x, y)
x
y
draw_point(**my_dict)
my_dict
'x': 10
'y': 20
x=10
y=20
# 示例:解包字典作为关键字参数
def create_config(host, port=8080, timeout=30):
print(f"Connecting to {host}:{port} with timeout {timeout}s.")
server_config = {"host": "localhost", "port": 9000}
create_config(**server_config)
# 输出:Connecting to localhost:9000 with timeout 30s.
full_config = {"host": "remote.server.com", "port": 80, "timeout": 60}
create_config(**full_config)
# 输出:Connecting to remote.server.com:80 with timeout 60s.这种解包机制的“高效”体现在它减少了样板代码,提高了代码的可读性和灵活性。它允许你将数据和函数调用逻辑解耦,使得你可以更专注于数据的组织和函数的行为,而不是如何将数据适配到函数参数上。这在我处理动态参数或需要将一个数据结构映射到函数调用时,是不可或缺的工具。
除了我们前面讨论的收集任意数量的位置参数(
*args
*
当你在函数参数列表中,在一个或多个位置参数之后,或者在
*args
*
# 示例:强制关键字参数
def generate_report(data_source, *, format="csv", destination="email", strict_mode=False):
"""
生成报告。
data_source:报告的数据来源(位置参数)。
format:报告格式(必须是关键字参数)。
destination:报告发送目的地(必须是关键字参数)。
strict_mode:是否启用严格模式(必须是关键字参数)。
"""
print(f"Generating report from {data_source}...")
print(f"Format: {format}")
print(f"Destination: {destination}")
print(f"Strict Mode: {strict_mode}")
# 正确的调用方式
generate_report("database", format="pdf", destination="ftp", strict_mode=True)
# 输出:
# Generating report from database...
# Format: pdf
# Destination: ftp
# Strict Mode: True
generate_report("web_api", format="json") # 使用默认值
# 输出:
# Generating report from web_api...
# Format: json
# Destination: email
# Strict Mode: False
# 错误的调用方式:尝试将 'pdf' 作为位置参数传递给 format
# generate_report("database", "pdf", "ftp")
# 这会引发 TypeError: generate_report() takes 1 positional argument but 3 were given在我看来,这种强制关键字参数的机制,对于设计清晰、易于理解和维护的API至关重要。它解决了几个实际问题:
generate_report(data, "pdf", "ftp")
generate_report(data, format="pdf", destination="ftp")
*
*
这种用法让函数签名本身成为了一种文档,它不仅定义了函数可以接受什么,还定义了它应该如何被调用。这对于构建健壮和用户友好的Python库来说,是一个非常有价值的特性。
以上就是python中函数参数前的星号(*)是什么意思?的详细内容,更多请关注php中文网其它相关文章!
python怎么学习?python怎么入门?python在哪学?python怎么学才快?不用担心,这里为大家提供了python速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号