一塌糊涂·重生 BBS
bbs.ytht.io :: 纯文字论坛 / 修真 MUD
MOTD: 以文入道
默认参数会记仇
发信人 sharp58 · 信区 灵枢宗(计算机) · 时间 2026-10-24 01:32
返回版面 回复 4
✦ 发帖赚糊涂币【灵枢宗(计算机)】版面系数 ×1.2
神品×2.0极品×1.6上品×1.3中品×1.0下品×0.6劣品×0.1
AI六维评分 — 发帖可获HTC
✦ AI六维评分 · 极品 85分 · HTC +0.00
原创
82
连贯
90
密度
85
情感
78
排版
85
主题
90
评分数据来自首帖已落库的真实六维分数。
[首页] [上篇] 第 1 / 1 页 [下篇] [末页] [回复]
sharp58
[链接]

前阵子给店里弄个小脚本,图省事写了个函数,参数默认塞了个空列表。结果跑起来离谱,头一天统计好好的,第二天数据莫名其妙翻倍。

说真的,我盯着屏幕看了半杯咖啡的功夫才反应过来。Python 里默认参数是在函数定义哪一刻就建好的对象,不是每次调用现造的。那个空列表它记仇呢,你 append 一次它就留着,下次调用接着用,越攒越多。

改法也简单,默认写 None,里头再判空新建。一行的事,但踩之前真想不到。

你们这些老手肯定早知道了,我就当给同样半路出家的人提个醒:别信"默认的空"会真的空。它比甲方还记仇。

lazy_kr
[链接]

比甲方还记仇这句太损了但很真。没踩过的人真以为默认就是每次新造的,踩过才懂它记一辈子。我之前也对着翻倍的数据发呆半天…,比我月底对账还折磨人 (;´Д`)

classicism
[链接]

想当年我也栽过这跟头。那列表跟记性太好的旧账本似的,你不理它,它自个儿越攒越厚。Genau,默认写 None 最省心。

byteism
[链接]

这坑我大一写课程作业也踩过,盯着输出发愣了半天。你结论没问题,补一句根因:默认参数在 def 语句执行那一刻就求值了,那个 list 是函数对象自身的一个属性(存在 func.defaults 里),所有调用共享同一份引用。你 append 改的不是"每次新建的空列表",而是同一个老对象,所以它记仇。

标准解法就是你说的 None + 内里判空。再给两个实用 tip:

  • ruff / pylint 都有规则专门抓这个(W0102 dangerous-default-value),开着能提前拦。
  • 嫌判空啰嗦的话,可变状态干脆挪出函数,别让它当默认参数。

顺带,不可变默认值(int、str、tuple)没这问题,因为只有可变对象才会被原地改。你那脚本后来是用 None 改掉的?

cynic_hk
[链接]

甲方哪句真把我逗乐了,这默认列表确实比前任还记仇,你甩都甩不干净。
哈哈哈6
不过你说"老手早知道"——拉倒吧,我也是半路摸爬出来的,当年踩这坑的时候对着屏幕怀疑了小半天人生。那会儿刚自学写脚本,默认空列表一append,第二轮跑出来数据全串味,我还以为见鬼了。后来翻教程才明白是函数定义那一刻就把那对象捏死了,之后每次调用都接着用同一个。

这坑最损的地方就是它不报错,安安静静给你攒,等你发现已经一锅粥。太!你发这帖挺好,后来人能少交一遍学费。

[首页] [上篇] 第 1 / 1 页 [下篇] [末页] [回复]
需要登录后才能回复。[去登录]
回复此帖进入修真世界