当前位置: 首页 > 面试题库 >

为什么在定义时评估默认参数?

盖晋
2023-03-14
问题内容

我很难理解算法中问题的根本原因。然后,通过逐步简化函数,我发现Python中对默认参数的求值行为不符合我的预期。

代码如下:

class Node(object):
    def __init__(self, children = []):
        self.children = children

问题是children,如果未显式给出属性,则Node类的每个实例都共享相同的属性,例如:

>>> n0 = Node()
>>> n1 = Node()
>>> id(n1.children)
Out[0]: 25000176
>>> id(n0.children)
Out[0]: 25000176

我不了解此设计决定的逻辑吗?为什么Python设计人员决定在定义时评估默认参数?这对我来说似乎很违反直觉。


问题答案:

另一种选择是重量级的-将“默认参数值”存储为函数对象的“ thunk”代码,每次调用该函数时都将为其重复执行而没有为该参数指定值-
并将使其早期绑定(在def时绑定)要困难得多,这通常是您想要的。例如,在存在的Python中:

def ack(m, n, _memo={}):
  key = m, n
  if key not in _memo:
    if m==0: v = n + 1
    elif n==0: v = ack(m-1, 1)
    else: v = ack(m-1, ack(m, n-1))
    _memo[key] = v
  return _memo[key]

…编写类似于上面的记忆功能是一项基本任务。类似地:

for i in range(len(buttons)):
  buttons[i].onclick(lambda i=i: say('button %s', i))

i=i依赖默认arg值的早期绑定(定义时间)的简单方法是获取早期绑定的简单方法。因此,当前规则是简单,直接的,它使您可以用一种非常容易解释和理解的方式来做所有您想做的事情:如果您想晚绑定一个表达式的值,请在函数体内评估该表达式;如果要早期绑定,请将其评估为arg的默认值。

如上述示例所示,另一种方法在两种情况下都要求延迟绑定,但不能提供这种灵活性,并且会迫使您每次需要早期绑定时都要经历一次麻烦(例如将函数包装到闭包工厂中)。这个假想的设计决定(除了在整个位置生成并反复评估击打的“隐形”击打之外),使程序员不得不承担更大的重量级样板。

换句话说,“应该有一种,最好只有一种明显的方法[1]”:当您想要后期绑定时,已经有一种非常明显的方法来实现它(因为该函数的所有代码仅被执行在调用时,显然一切评价
还有 就是后期绑定); 让default-
arg评估产生早期绑定也为您提供了一种实现早期绑定的明显方法(一个加号!!),而不是给了两种明显的方法来进行晚期绑定,而没有给出一种明显的方法来进行早期绑定(减号!!)。

[1]:“尽管起初,除非您是荷兰人,否则这种方式可能并不明显。”



 类似资料:
  • 问题内容: 为什么这段代码会引发SyntaxError? 尽管以下代码段运行时没有可见错误: 问题答案: 必须将所有必需的参数放在任何默认参数之前。仅仅是因为它们是强制性的,而默认参数不是必需的。从语法上讲,如果允许使用混合模式,解释器将 无法 决定哪些值与哪些参数匹配。如果参数的输入顺序不正确,则会引发A : 让我们使用您的函数来查看关键字参数。 假设其允许声明函数如上,然后使用上述声明,我们可

  • 问题内容: 有谁知道,为什么Oracle的(和)函数总是对第二个参数求值,即使第一个参数不是呢? 简单测试: 返回,但也打印。 已调用,即使由于第一个参数不是,结果也被忽略了。 问题答案: 一直都是这种方式,因此Oracle必须保持这种方式以保持向后兼容。 使用,而不是让短路行为。

  • 问题内容: 对于我确定的人来说,这是一个简单的答案。有人可以解释为什么此表达式的值为真吗? 问题答案: 因为您使用的是==(相似性)运算符,而PHP将字符串强制为int。 要解决此问题,请使用===(等于)运算符,该运算符不仅会检查值是否相同,还会检查数据类型是否相同,因此“ 123”字符串和123 int不会被视为相等。

  • 我理解经典例子的问题 但我无法说服自己以下是有效的还是无效的 我知道'foo(i)'和'i'的求值顺序是不确定的,但是'评估'到底是什么意思?也就是说bar的第二个参数总是42,或者'i'的当前值可以在foo改变它之前被传入吗?

  • 问题内容: 在python中进行如下构造是有效的: 我想问一个函数指针被评估为True的逻辑是什么。 为什么在语言中插入这种构造? 问题答案: 在Python中有很多评估结果。从关于布尔运算符的文档中: 在布尔运算的上下文中,以及当控制流语句使用表达式时,以下值将解释为false:,,所有类型的数字零以及空字符串和容器(包括字符串,元组,列表,字典,集合和Frozensets)。所有其他值均解释为

  • 问题内容: 在SQL Server中,如果 在where子句中,则其总值为false。这是违反直觉的,并导致了我很多错误。我确实了解和关键字是正确的方法。但是,为什么SQL Server会以这种方式表现呢? 问题答案: 在这种情况下,请将null视为“未知”(或“不存在”)。在这两种情况下,您都不能说它们相等,因为您不知道它们的价值。因此,null = null的计算结果不为true(false或