导读:本期聚焦于新加坡程序员创作的《python函数形参如何设置默认值?参数默认值详解与避坑指南》,敬请观看详情。给函数参数设置默认值是Python里非常常用的技巧,调用时可以少传参数,让代码更简洁。本文详细讲解def定义函数时如何用等号给形参赋默认值,默认参数的匹配规则,以及必选参数、默认参数、可变参数、关键字参数的排列顺序要求。同时重点分析默认值使用可变对象(如列表、字典)时经典的坑,解释Python只在函数定义时求值一次默认值的底层原因,并给出用None作哨兵值的正确写法,帮助你在实际开发中正确使用参数默认值。

在Python中定义函数时,给形参设置默认值能让调用方省去不必要的传参工作,接口也变得更灵活。语法本身很简单,在参数列表里用等号给参数赋一个初始值即可,但默认值的求值时机、参数排列顺序以及可变默认值带来的隐患,都有值得深入理解的地方。本文从基础语法讲起,逐步展开这些细节。

python函数形参如何设置默认值?参数默认值详解与避坑指南

一、设置默认值的基本语法

定义函数时,在形参后面直接跟上=和一个值,这个值就成为该参数的默认值。调用函数时如果没有传入这个参数,函数就会使用默认值;如果传了,就用传入的值覆盖默认值。

def greet(name, greeting="你好"):
    print(greeting + ", " + name)

greet("小明")            # 输出:你好, 小明
greet("小红", "早上好")   # 输出:早上好, 小红</code>

上面的例子中,greeting就是带默认值的参数。第一次调用只传了一个位置参数,greeting自动取默认值“你好”;第二次调用显式传入了“早上好”,默认值被覆盖。

默认值可以设置为函数返回值或表达式,比如def foo(x, y=2*3)是完全合法的。但要注意,这个表达式只在函数定义那一刻被求值一次,而不是每次调用时都重新求值,这一点在后面会详细展开。

二、参数的排列顺序有严格要求

Python规定:带默认值的参数必须放在不带默认值的参数(必选参数)之后。如果顺序写反了,解释器在语法解析阶段就会直接报错。

# 错误写法:默认参数放在了必选参数前面
def bad(a=1, b):
    pass
# SyntaxError: non-default argument follows default argument

# 正确写法
def good(a, b=1):
    pass

完整的参数顺序规则是:位置参数 → 默认参数 → 可变参数(*args)→ 关键字参数 → 关键字可变参数(**kwargs)。举个例子:

def func(a, b=10, *args, key, **kwargs):
    print(a, b, args, key, kwargs)

func(1, 2, 3, 4, key="k", x=5, y=6)
# 输出:1 2 (3, 4) k {'x': 5, 'y': 6}

这样设计的原因很好理解:如果默认参数放在前面,调用时用位置传参,解释器就无法判断后面的实参到底对应谁。牢记这个顺序,可以避免大部分函数定义时的语法错误。

三、可变默认值是最大的坑

默认值最容易出问题的地方,是把列表、字典、集合这类可变对象设为默认值。看一个经典例子:

def add_item(item, items=[]):
    items.append(item)
    return items

print(add_item(1))  # 输出:[1]
print(add_item(2))  # 输出:[1, 2]
print(add_item(3))  # 输出:[1, 2, 3]

很多人期望每次调用都得到一个新列表,但实际输出却是累积的结果。原因在于:默认值在函数定义时只求值一次,这个[]被绑定到了函数对象的一个属性上,之后所有调用共享同一个列表对象。

可以用add_item.__defaults__查看函数的默认值,你会发现它保存的就是那个被反复修改的列表。这从底层证实了默认值与函数对象绑定,而不是与某次调用绑定。

正确的做法是用None作为哨兵值,在函数体内判断后再创建新对象:

def add_item(item, items=None):
    if items is None:
        items = []
    items.append(item)
    return items

print(add_item(1))  # 输出:[1]
print(add_item(2))  # 输出:[2]

注意这里应该用is None判断,而不是items == Noneif not items。因为如果调用方传入了一个空列表,if not items会误判,导致传入的列表被丢弃。这是一个容易被忽视的细节。

四、默认值的其他实用技巧

默认值配合关键字调用可以让代码可读性大幅提升,尤其在参数较多时,明确写出参数名能避免传错顺序:

def create_user(name, age=18, city="北京", vip=False):
    print(name, age, city, vip)

create_user("张三", city="上海", vip=True)  # 跳过age只传city和vip

另外,默认值可以引用前面已经出现的参数,这能实现一种依赖参数的写法:

def report(width, height, area=width * height):
    return area

不过这种写法在Python中并不支持(会报NameError),因为在函数定义时参数名还未在可访问的作用域内。如果需要基于其他参数计算默认值,同样要借助None哨兵,在函数体内处理。

还有一种场景是需要区分“调用方没传”和“调用方传了None”。此时可以定义一个模块级的哨兵对象,比如_MISSING = object(),然后判断if x is _MISSING,这样即使调用方显式传None也能被正确识别。

总结

给Python函数的形参设置默认值,核心语法是def f(a, b=默认值),记住三点就不会踩坑:一是默认参数必须放在必选参数之后;二是默认值只在定义时求值一次,可变对象作默认值会被共享,务必用None哨兵值代替;三是函数体内判断时用is None,既准确又符合Python的惯用写法。掌握这些规则后,默认参数会成为你设计函数接口时非常好用的工具。

python函数默认参数形参默认值修改时间:2026-09-04 04:48:30

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/20260904/50020.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。