【问题标题】:question about python names using a default parameter value关于使用默认参数值的python名称的问题
【发布时间】:2010-08-12 05:40:30
【问题描述】:

我今天正在阅读这篇文章:http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#default-parameter-values,我似乎无法理解幕后发生的事情。

def bad_append(new_item, a_list=[]):
    a_list.append(new_item)
    return a_list

这里的问题是默认 a_list 的值,一个空列表,是 在函数定义时评估。 所以每次调用函数时, 你得到相同的默认值。尝试一下 几次:

我想首先,函数定义阶段是什么时候?是在实际 main 函数执行之前的初始化阶段吗?

我最初的想法是在函数运行后名称 a_list 会立即被丢弃,因此无论 [] 突变为什么都将被垃圾收集。现在,我认为 a_list 根本没有被丢弃,因为它只是绑定到对象 [] 的名称,因此它永远不会被垃圾收集,因为 a_list 仍然绑定到它。但话又说回来,我想知道我如何仍然获得相同的默认值而不是新的[]。有人可以为我解决这个问题吗?

谢谢!

【问题讨论】:

    标签: python variables


    【解决方案1】:

    函数定义阶段是什么时候?

    查看 Python 参考中的"Function definitions"

    在执行函数定义时计算默认参数值。这意味着在定义函数时计算一次表达式,并且相同的“预计算”值用于每次通话。当默认参数是可变对象(例如列表或字典)时,这一点尤其重要:如果函数修改了对象(例如,通过将项目附加到列表中),则默认值实际上已被修改。这通常不是预期的。解决这个问题的一种方法是使用None 作为默认值,并在函数体中显式测试它,例如:

    def whats_on_the_telly(penguin=None):
        if penguin is None:
            penguin = []
        penguin.append("property of the zoo")
        return penguin
    

    在执行函数定义时评估参数。如果这是在模块中,则在导入模块时发生。如果它在一个类中,那就是类定义运行的时候。如果它在一个函数中,它会在函数执行时发生。请记住,Python 模块是从上到下进行评估的,并且不会像某些语言那样自动具有显式的“主函数”。

    例如,如果将函数定义放在函数内部,则每次都会得到该函数的新副本:

    >>> def make_function():
    ...     def f(value=[]):
    ...             value.append('hello')
    ...             return value
    ...     return f
    ... 
    >>> f1 = make_function()
    >>> f2 = make_function()
    >>> f1()
    ['hello']
    >>> f1()
    ['hello', 'hello']
    >>> f2()
    ['hello']
    

    函数定义创建一个新的function 对象,为其分配包括代码、形式参数和默认值在内的各种属性,并将其存储在范围内的名称中。通常,对于任何给定函数,这只会发生一次,但在某些情况下,函数的定义可以再次执行。

    我最初的想法是,名称 a_list 在函数运行后立即被丢弃,因此无论 [] 突变为什么都将被垃圾收集。

    在函数体内,代码可以使用名称a_list。因此,名称和它所指向的值都必须仍然可用。它存储在函数的func_defaults 属性中。

    但话又说回来,我想知道我如何仍然获得相同的默认值而不是新的 []。

    因为 [] 仅在定义函数时进行评估,而不是在调用它时进行评估,并且名称 a_list 指向同一个对象,即使在重复调用时也是如此。同样,如果您想要替代行为,请使用不可变的东西,例如 None 并检查它。

    【讨论】:

      猜你喜欢
      • 2020-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-17
      • 2012-08-01
      • 2010-10-22
      • 2020-07-21
      • 2020-12-02
      相关资源
      最近更新 更多