Python函数参数设计需理解“参数何时被创建”“值如何传递”“对象是否可变”三大逻辑:默认参数在定义时求值,可变对象作默认值易出错,应以None代替并在函数内初始化;args收集剩余位置参数为元组;kwargs收集剩余关键字参数为字典;参数顺序应为普通参数→args→默认参数→kwargs,兼顾灵活性与可读性。

Python函数的参数设计灵活而强大,默认参数和可变参数是日常开发中最常用也最容易出错的两个特性。掌握它们的关键,不在于死记语法,而在于理解“参数何时被创建”“值如何被传递”“对象是否可变”这三个底层逻辑。
默认参数:只在定义时计算一次
默认参数的值在函数定义时就被求值并绑定,而不是每次调用时重新生成。这对不可变对象(如数字、字符串、None)影响不大,但对可变对象(如列表、字典)可能引发意外行为。
常见陷阱示例:
def add_item(item, lst=[]): # 危险!默认列表在定义时创建
lst.append(item)
return lst
print(add_item(1)) # [1]
print(add_item(2)) # [1, 2] ← 意外!复用了上次的列表
正确写法是用 None 作占位符,在函数体内初始化:
立即学习“Python免费学习笔记(深入)”;
- 始终用 None 作为可变默认参数的占位值
- 在函数开头显式判断并创建新对象:
if lst is None: lst = [] - 避免在默认值中调用会改变状态的函数(如
datetime.now())
*args:收集位置参数为元组
*args 把所有未匹配的位置参数打包成一个 tuple,它必须放在普通参数之后、**kwargs 之前。
典型用途:
- 封装或转发参数:比如写一个日志装饰器,需要原样传入被装饰函数的所有参数
- 实现类似内置函数的接口:如
sum(*numbers)或自定义的max_by_key(key_func, *items) - 与解包配合使用:
func(*[1,2,3])等价于func(1,2,3)
注意:*args 不捕获关键字参数,也不会影响参数名匹配;它只是“剩下的位置参数”。如果调用时混用位置和关键字,已命名的参数仍需满足签名要求。
系统模块主要有:1、网站栏目可以自定义网站栏目,自定义的网站栏目可以分为两个级别层次,当然也可以只做一个层次,设置新网站栏目后编辑网站栏目的内容;默认栏目有些可以关闭和开启。2、物品展示系统与以往网站系统不同的是,该物品展示系统可以从0全部自定义物品的所有参数和信息;因为每种物品的详细参数是不一样的,如手机和笔记本参数完全不一样;可以自定义新物品的参数,然后自定义物品的次级和三级物品分类,大大实现
**kwargs:收集关键字参数为字典
**kwargs 将所有未被显式声明的关键字参数收集成一个 dict。它必须是参数列表中的最后一个。
实用技巧:
- 用于配置类或函数的“灵活选项”:
def create_plot(data, **plot_opts): plt.plot(data, **plot_opts) - 安全地传递子组件参数:父函数只处理自己关心的参数,其余通过 **kwargs 透传
- 检查非法关键字:
allowed = {'color', 'linewidth', 'alpha'}; invalid = set(kwargs) - allowed
提醒:不要在函数内部直接修改 kwargs 字典(如 kwargs.pop('debug')),除非你明确知道后续代码不再依赖它;更推荐用 kwargs.get('debug', False) 安全读取。
组合使用:顺序与可读性优先
合法的完整参数顺序是:普通参数 → *args → 默认参数 → **kwargs(Python 3.8+ 支持仅限位置参数 /,但此处不展开)。
例如:
def send_request(url, *args, timeout=30, verify=True, **headers):
...
这样调用都合法:
send_request("https://api.com")-
send_request("https://api.com", "POST", json={"x":1})("POST"进 args,json 进 headers) send_request("https://api.com", timeout=5, Authorization="Bearer...")
关键原则:参数顺序要让人一眼看出哪些是必填、哪些是扩展、哪些是配置;避免过度堆砌 *args/**kwargs,必要时拆分成多个明确命名的参数提升可维护性。









