Python内置函数deepcopy使用可变默认参数是否合理?
deepcopy Use a Mutable Default Argument? Great question! Let’s clear this up: the mutable default argument _nil=[] in Python’s deepcopy function is intentional design, not a mistake. Here’s why it makes sense, even though mutable defaults are usually a pitfall:
First, a Quick Recap of the Mutable Default Pitfall
We all know the classic gotcha:
def add_item(lst=[]): lst.append(1) return lst
Calling this function repeatedly reuses the same list instance, leading to unexpected results. But this only causes problems when the default object is modified and shared across calls.
How _nil Works in deepcopy
Looking at the deepcopy definition:
def deepcopy(x, memo=None, _nil=[]):
The _nil parameter serves a specific, safe purpose: it’s a private sentinel value to check if an object has already been copied (and stored in the memo dictionary).
Here’s the key logic from the source:
y = memo.get(d, _nil) if y is not _nil: return y
_nilis created exactly once when the function is defined, so it’s a unique object that no user can access (it’s prefixed with an underscore, signaling it’s internal-only).- When checking the
memocache, if the object’s ID isn’t found,memo.get()returns_nil. We then useiscomparison (which checks object identity) to confirm whether we’ve already processed the object.
Why This Doesn’t Cause the Mutable Default Pitfall
Unlike the classic example:
_nilis never modified anywhere in thedeepcopycode. It’s only used as a marker for "not found in memo".- Users never pass a value for
_nil—it’s strictly an internal parameter. There’s no way for external code to alter it, so there’s no risk of shared state across calls.
Why Not Use a Different Sentinel?
You might wonder why they didn’t use something like object() (a unique immutable object) instead of a list. The answer is simplicity: a list is a quick, easy way to create a unique, unshared object. Since it’s never modified, using a list here is harmless and achieves the goal perfectly.
In short, this is a clever use of Python’s function default argument behavior—leveraging the fact that mutable defaults are created once, while avoiding the common pitfalls by keeping the parameter private and unmodified.
内容的提问来源于stack exchange,提问作者DeepSpace

