最近刷牛客网。
看到一道连续几年都在出现的Python面试题。
题目只有几行代码:
def append_item(item, data=[]): data.append(item) return dataprint(append_item(1))print(append_item(2))
如果是你。
会输出什么?
很多人第一反应:
结果。
错了。
真正的输出是:
第一次看到的人。
几乎都会愣一下。
😳
这也是为什么阿里、字节跳动、美团、百度等互联网公司的Python面试,特别喜欢考这道题。
因为它考的不是语法。
而是:
你到底懂不懂Python。
为什么会这样?
很多人认为。
函数每执行一次。
默认参数都会重新创建。
其实不是。
Python规定:
默认参数只会在函数定义时创建一次。
也就是说:
不是每调用一次就创建一个新列表。
而是:
整个程序运行期间。
这个列表一直存在。
第一次执行:
列表变成:
第二次执行:
Python继续使用同一个列表。
于是:
就出现了。
是不是有点反直觉?
没错。
但这正是Python的设计。
面试官真正想听什么?
如果你的回答只是:
因为默认参数只初始化一次。
只能算及格。
真正优秀的回答应该继续解释:
Python这样设计。
其实是为了减少重复创建对象。
提高函数调用效率。
因为不可变对象:
完全没有问题。
真正危险的是:
这些可变对象。
它们会共享状态。
这才是Bug产生的根源。
正确写法是什么?
几乎所有资深Python开发都会这样写:
def append_item(item, data=None): if data is None: data = [] data.append(item) return data
为什么不用:
因为:
空列表:
也是False。
如果业务允许传空列表。
逻辑就会出错。
因此:
判断默认参数。
永远推荐:
这一点。
也是牛客网上出现频率很高的追问。
为什么大厂喜欢考这种题?
因为真实项目里。
这种Bug特别难查。
举个例子。
你写了一个缓存函数:
def cache(value, result=[]): ...
上线之后。
缓存越来越大。
数据越来越乱。
排查了两天。
最后发现:
默认参数一直在共享。
这类问题。
不是不会写代码。
而是:
没有理解对象生命周期。
一个微软工程师分享过一句话
Bug最可怕的地方,不是报错,而是它一直在正常运行。
这句话放到Python里。
再合适不过。
可变默认参数。
程序不会崩。
不会报异常。
甚至还能正常输出。
直到某一天。
线上数据越来越奇怪。
你才开始怀疑人生。
😂
AI时代,这类题为什么越来越重要?
很多人说:
现在有AI。
这些基础知识不用学了。
我的看法正好相反。
AI确实可以生成:
甚至整个模块。
但是。
AI不会替你承担责任。
如果生成的代码存在隐藏Bug。
最终排查的人。
还是工程师。
真正值钱的能力。
已经不是:
写代码。
而是:
识别代码中的风险。
牛客网面经透露了一个趋势
最近几年。
Python面试越来越少问:
会不会Django?
越来越多问:
这些问题。
看起来都是基础。
实际上。
考察的是:
语言底层原理。
我的一个观点
很多程序员每天收藏面试题。
背答案。
刷八股。
看起来很努力。
实际上成长很慢。
为什么?
因为:
答案可以背。
理解不能背。
比如今天这道题。
真正值得思考的不是:
为什么输出:
而是:
为什么Python要这样设计?
理解了这一点。
你不仅学会了默认参数。
还理解了:
这才是一题多得。
写在最后
很多人觉得。
Python简单。
所以容易学。
其实。
Python真正难的地方。
从来不是:
而是那些只有几行代码。
却能问倒无数人的底层细节。
未来AI会帮我们写更多代码。
但真正决定技术上限的。
依然是:
你是否理解代码为什么这样运行。
所以。
下次如果面试官问你:
为什么Python不建议把List作为默认参数?
不要急着回答:
因为会共享。
再多说一句:
因为默认参数在函数定义阶段只创建一次,可变对象会在多次调用之间共享状态,因此推荐使用None作为占位符,再在函数内部创建新对象。
这一句。
往往就是普通回答和优秀回答之间的差距。🚀
点个「在看」👍
愿你每学一个Python知识点,都不仅知道"怎么写",更知道"为什么这样写"。