<p>为了有效地使用默认值,您需要了解默认值是如何工作的。</p>
<p>函数是对象。因此,它们具有属性。所以,如果我创建这个函数:</p>
<pre><code>>>> def f(x, y=[]):
y.append(x)
return y
</code></pre>
<p>我创建了一个对象。其特点如下:</p>
<pre><code>>>> dir(f)
['__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__',
'__dict__', '__doc__', '__format__', '__get__', '__getattribute__', '__globals__',
'__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__',
'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals',
'func_name']
</code></pre>
<p>其中之一是<code>func_defaults</code>。听起来不错,里面有什么?</p>
<pre><code>>>> f.func_defaults
([],)
</code></pre>
<p>这是一个包含函数默认值的元组。如果默认值是对象,则元组包含该对象的实例。</p>
<p>如果您认为<code>f</code>向列表中添加了一个项,而在没有提供列表的情况下返回仅包含该项的列表,则会导致一些相当违反直觉的行为:</p>
<pre><code>>>> f(1)
[1]
>>> f(2)
[1, 2]
</code></pre>
<p>但是,如果您知道默认值是存储在函数属性之一中的对象实例,那么它就不那么违反直觉了:</p>
<pre><code>>>> x = f(3)
>>> y = f(4)
>>> x == y
True
>>> x
[1, 2, 3, 4]
>>> x.append(5)
>>> f(6)
[1, 2, 3, 4, 5, 6]
</code></pre>
<p>知道了这一点,很明显,如果希望函数参数的默认值是一个新列表(或任何新对象),就不能简单地将对象的实例保存在<code>func_defaults</code>中。每次调用函数时都必须创建一个新的:</p>
<pre><code>>>>def g(x, y=None):
if y==None:
y = []
y.append(x)
return y
</code></pre>