gpt4 book ai didi

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

转载 作者:IT老高 更新时间:2023-10-28 21:49:02 24 4
gpt4 key购买 nike

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

代码如下:

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

问题是Node类的每个实例共享相同的children属性,如果属性没有明确给出,例如:

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

我不明白这个设计决策的逻辑?为什么 Python 设计者决定在定义时评估默认参数?这对我来说似乎非常违反直觉。

最佳答案

替代方案将是相当重量级的——在函数对象中存储“默认参数值”作为代码的“thunk”,每次调用函数时都会一遍又一遍地执行而没有为该参数指定值——并且会使获得早期绑定(bind)(在定义时间绑定(bind))变得更加困难,这通常是您想要的。例如,在现有的 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 值的早期绑定(bind)(定义时间),是获得早期绑定(bind)的一种非常简单的方法。因此,当前规则简单明了,让您以一种非常容易解释和理解的方式做所有您想做的事情:如果您想要后期绑定(bind)表达式的值,请在函数体中评估该表达式;如果您想要提前绑定(bind),请将其评估为 arg 的默认值。

在这两种情况下强制后期绑定(bind)的替代方案不会提供这种灵 active ,并且会在您每次需要早期绑定(bind)时强制您进行循环(例如将您的函数包装到闭包工厂中),如上面的示例所示-- 这个假设的设计决策强加给程序员更多的重量级样板(除了在所有地方生成和反复评估thunk的“不可见”的样板)。

换句话说,“应该有一个,最好只有一个,明显的方法来做到这一点[1]”:当你想要后期绑定(bind)时,已经有一个非常明显的方法来实现它(因为所有函数的代码仅在调用时执行,显然 there 评估的所有内容都是后期绑定(bind)的);让 default-arg 评估产生早期绑定(bind)为您提供了一种实现早期绑定(bind)的明显方法(加号!-),而不是提供两种明显的方式来获得后期绑定(bind),而没有明显的方式来获得早期绑定(bind)(减号!-)。

[1]:“虽然这种方式一开始可能并不明显,除非你是荷兰人。”

关于python - 为什么在定义时评估默认参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1651154/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com