【问题标题】:Why do named arguments in python have consistent memory? [duplicate]为什么python中的命名参数具有一致的内存? [复制]
【发布时间】:2019-08-06 17:15:38
【问题描述】:

以下代码

def f(x,l=[]):
    for i in range(x):
        l.append(i*i)
    print(l) 

f(2)
f(3)

输出

[0, 1]

[0, 1, 0, 1, 4]

不是小事

[0, 1]

[0, 1, 4]

这意味着命名参数 l 实际上是一个一致的变量,在新调用 f 时不会重置。

这显然不是错误,而是设计使然。

我的问题是为什么这是理想的行为?对我来说,这似乎更令人困惑而不是有用,这会让我永远不想使用不可变的默认值。

【问题讨论】:

  • 默认值的计算成本可能比空列表字面值高得多,在这种情况下,您只需在定义函数时评估它一次,而不是每次调用函数。
  • 另外,已经有一种方法可以在每次调用时执行代码:将其放在函数体中。
  • @chepner 关于您的第二条评论 - 显然将代码放入函数体中会在每次调用时执行它。但是在命名参数中放置一个变量真的是创建“静态”变量的pythonic方式吗?
  • @Gulzar 将默认 arg 设为不可变类型是 pythonic。但是,如果这就是 static 的意思,它不会强制输入。这就是为什么你可以拥有some_arg=None 并用不同的类型替换它
  • @Gulzar 创建 C 风格静态变量的 Pythonic 方法是定义类的方法。但仅仅因为可变默认参数没有强大或明显的用例并不意味着有令人信服的理由禁止它。

标签: python reference pass-by-reference default-value


【解决方案1】:

函数定义一次,因此当使用可变类型的默认参数时,它们使用对该默认参数的单个引用(因为它再次定义一次)。这就是为什么在不可变类型(如 None、int、str 等)上使用列表、字典等作为默认参数是不好的做法。

举个例子:


def mutable_arg(x=[]):
    x.append(3)
    print(x)

def immutable_arg(x=None):
    x = x or []
    x.append(3)
    print(x)

mutable_arg() # prints [3]
mutable_arg() # prints [3,3]
immutable_arg() # prints [3]
immutable_arg() # prints [3]

immutable_arg 中,它为每个调用创建一个新列表,而不是重新使用与mutable_arg 中相同的默认值

【讨论】:

  • 我了解发生这种情况的机制。正如问题中所解释的,我也意识到为什么这是不好的做法。但是,我不明白为什么这是设计选择。为什么一开始就允许这个陷阱,而不是自动重新初始化?
  • 然后查看@chepner 的评论。为什么您想要每次都重新定义参数?
猜你喜欢
  • 1970-01-01
  • 2012-11-06
  • 1970-01-01
  • 2012-08-06
  • 2011-03-09
  • 2018-12-24
  • 2014-06-01
  • 1970-01-01
  • 2016-08-29
相关资源
最近更新 更多