一文了解 Python 函数参数(/、*args、*、**kargs)
Python 支持五种关键类型的函数参数。让我们看看每种参数类型,并讨论它们如何工作以及何时使用它们的具体规则。我们将通过示例来研究每个示例,重点关注实际应用程序。
函数参数的五种类型
- 仅位置参数( / )
- 位置或关键字参数(默认)
- 仅关键字参数( * )
- 可变长度位置参数( *args )
- 可变长度关键字参数( **kwargs )
1. 仅位置参数
仅位置参数是使用函数签名中的/符号定义的。调用函数时,这些参数必须按其位置传递。您不能使用他们的名字作为关键字。
为什么使用仅位置参数?
- 它们强调简单性,尤其是在参数名称不增加值的函数中。
- 它们可以防止由关键字参数引起的意外行为。
示例:简单的折扣计算器
def calculate_discount(price, discount_rate, /):
"""Calculate the discounted price given a price and a discount rate."""
return price - (price * discount_rate)
# Correct usage
print(calculate_discount(100, 0.2)) # Output: 80.0
# Incorrect usage (will raise a TypeError)
# print(calculate_discount(price=100, discount_rate=0.2))
解释:
- 函数签名中的/指定price和discount_rate只能作为位置参数传递。
- 如果您尝试将它们作为关键字参数传递(例如, price=100 ),Python 将引发TypeError 。
真实场景:在创建数学运算或日志记录等实用函数时,您可能会使用仅位置参数,其中参数名称不会提高清晰度。
2. 位置或关键字参数
默认情况下,Python 允许您按位置或按名称将参数传递给函数。这是最常用的参数类型。
示例:用户注册功能
def register_user(username, email, is_active=True):
"""Register a new user with an optional active status."""
return {
"username": username,
"email": email,
"is_active": is_active,
}
# Passing arguments by position
print(register_user("johndoe", "john@example.com"))
# Passing arguments by keyword
print(register_user(username="janedoe", email="jane@example.com", is_active=False))
解释:
- 您可以通过位置( "johndoe", "john@example.com" )或关键字( username="janedoe" )传递username和email 。
- is_active参数有一个默认值 ( True ),因此除非明确提供,否则它是可选的。
真实场景:此类函数用于创建对象或配置设置,其中默认值使函数更易于使用。
3. 仅关键字参数
仅关键字参数在函数签名中的*之后定义。这些参数必须按名称传递,以确保清晰。
示例:安排会议
def schedule_meeting(*, day, time):
"""Schedule a meeting with specific day and time."""
return f"Meeting scheduled on {day} at {time}."
# Correct usage
print(schedule_meeting(day="Monday", time="2 PM"))
# Incorrect usage (will raise a TypeError)
# print(schedule_meeting("Monday", "2 PM"))
解释:
- *强制要求day和time必须作为关键字参数传递。
- 这可以避免调用中的混乱,尤其是在具有多个参数的函数中。
真实场景:仅关键字参数非常适合参数名称提高可读性的 API 或配置函数。
4. 可变长度位置参数 (*args)
当需要处理任意数量的位置参数时,请使用*args 。这些被收集到一个元组中。
示例:记录多条消息
def log_messages(log_level, *messages):
"""Log multiple messages with a specific log level."""
print(f"Log Level: {log_level}")
for message in messages:
print(f"- {message}")
# Passing multiple messages
log_messages("INFO", "Server started", "Connection established", "Ready to accept requests")
解释:
- 第一个参数 ( log_level ) 是常规位置参数。
- *messages将所有附加参数收集到一个元组中,允许该函数处理任意数量的消息。
现实场景:这样的函数通常用于日志记录或数据聚合,其中输入数量不固定。
5. 可变长度关键字参数 (**kwargs)
使用**kwargs接受任意数量的关键字参数。这些都被收集到字典中。
示例:配置应用程序
def configure_app(**settings):
"""Configure an application with dynamic settings."""
print("App Configuration:")
for key, value in settings.items():
print(f"{key}: {value}")
# Passing dynamic settings
configure_app(debug=True, database_url="sqlite:///:memory:", port=8080)
解释:
- **settings将所有关键字参数收集到字典中。
- 这使得功能灵活,可满足不同的配置需求。
真实场景:您可以在设置加载器、表单处理程序或动态 API 中使用**kwargs 。
组合参数类型
您可以在单个函数中混合这些参数类型,但它们必须遵循以下顺序:
- 仅位置 ( / )
- 位置或关键字
- 可变长度位置 ( *args )
- 仅关键字 ( * )
- 可变长度关键字 ( **kwargs )
示例:多功能 API 请求函数
def api_request(method, endpoint, *args, headers=None, **params):
"""Make an API request with flexible arguments."""
print(f"Method: {method}")
print(f"Endpoint: {endpoint}")
if args:
print("Additional Arguments:", args)
if headers:
print("Headers:", headers)
if params:
print("Parameters:", params)
# Making a flexible API request
api_request(
"GET",
"/users",
"pagination",
headers={"Authorization": "Bearer token"},
sort="name",
filter="active",
)
解释:
- method和endpoint是位置或关键字参数。
- *args收集额外的位置参数(例如, "pagination" )。
- headers是一个仅限关键字的参数。
- **params收集动态关键字参数(例如, sort="name", filter="active" )。