TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

The Perils of Default Arguments in Python

1 点作者 going_north2 个月前

1 comment

zahlman2 个月前
Yes, this is the subject of one of the &quot;classic&quot; posts of OG Stack Overflow (<a href="https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;1132941" rel="nofollow">https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;1132941</a>). And in fact it commonly gets deliberately abused (<a href="https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;3431676" rel="nofollow">https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;3431676</a>) despite better tools being available for the intended effect (<a href="https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;277922" rel="nofollow">https:&#x2F;&#x2F;stackoverflow.com&#x2F;questions&#x2F;277922</a>).<p>But it&#x27;s good to have more writeups, I suppose. And it&#x27;s good to point out that the initializers of a `dataclass` will show the same kind of early binding, and how to use `default_factory` instead. (It&#x27;s not immediately obvious that this is related to the issue with function arguments, but it is.)<p>&gt; That is a very roundabout way of saying that if you do this... the default argument value for base_url will be &quot;eaj.no&quot;, and not &quot;example.com&quot;.<p>This isn&#x27;t a good example. Even in a hypothetical alternate Python where `base_url` had its default value read at call time, `some_function` isn&#x27;t called anywhere, nor does it modify the global `default_url`, so there&#x27;s no reason why the behaviour of `get_post_url` would change.<p>&gt; Notably, we can also pass a variable as the default argument value.<p>No; as already established, a <i>value</i> is used - the value that results from evaluating the <i>expression</i> `default_url` (which happens to consist of just a variable name). Also, default argument values aren&#x27;t &quot;passed&quot; - that&#x27;s the point.<p>&gt; In short, default arguments should never be used for values that are required to change between function calls.<p>More accurately, subsuming the previous section: they should not be used for values that must <i>be determined at the time the function is called</i>. Because that isn&#x27;t what happens.<p>&gt; Use None as a sentinel value and conditionally create the mutable default value in the function body instead.<p>This is the standard advice, but I hate it. &quot;Special cases aren&#x27;t special enough to break the rules&quot;; `None` is overly magical in a lot of Python code. Besides, writing code that modifies the passed-in value and then also `return`s a value isn&#x27;t Pythonic - <a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Command%E2%80%93query_separation" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Command%E2%80%93query_separati...</a> is a key part of the design of the standard library and of several builtin methods. Maybe you expect the caller to use a temporary for every call, but maybe the caller didn&#x27;t understand that.<p>A lot of the time, a better approach is to just use an equivalent immutable value.