我的意图是创建一个字典,其中的键是原语,其值是返回字符串的零参数函数。(这是实现 VM 的更大项目的一部分。)其中某些功能非常重要,需要手动创建和分配。那些工作正常。然而,其他人似乎适合自动生成。
我的第一次尝试失败了:
>>> regs = ['a', 'b', 'c', 'x', 'y', 'z']
>>> vals = {i : lambda: r for i, r in enumerate(regs)}
>>> [(k, vals[k]()) for k in vals.keys()]
[(0, 'z'), (1, 'z'), (2, 'z'), (3, 'z'), (4, 'z'), (5, 'z')]
好的; lambda 函数在被调用之前不会读取 r。我又试了一次,试图自己隔离一个值:
>>> from copy import copy
>>> vals = {}
>>> i = 0
>>> for reg in regs:
... r = copy(reg) # (1)
... vals[i] = lambda: r
... i += 1
...
>>> [(k, vals[k]()) for k in vals.keys()]
[(0, 'z'), (1, 'z'), (2, 'z'), (3, 'z'), (4, 'z'), (5, 'z')]
(1) 我认为这一步会创建一个独立变量,当 reg 发生时不会改变。事实证明并非如此。
所以这种尝试显然没有奏效。也许复制,在一个字符串上,是一个 noop?
>>> 's' is 's'
True
>>> a = 's'
>>> b = copy(a)
>>> a is b
True
>>> from copy import deepcopy
>>> b = deepcopy(a)
>>> a is b
True
对。复制,在一个字符串上,是一个 noop。Deepcopy 不能解决这个问题。因此,lambda 仍然有对在每个循环中更新的变量的引用,从而导致了这个错误。
我们需要一种不同的方法。如果我将我想要的变量保存到临时函数的静态变量中怎么办?如果每个临时函数都有自己的身份,那应该可以工作......
>>> vals = {}
>>> i = 0
>>> for reg in regs:
... def t():
... return t.r
... t.r = reg
... vals[i] = t
... i += 1
...
>>> [(k, vals[k]()) for k in vals.keys()]
[(0, 'z'), (1, 'z'), (2, 'z'), (3, 'z'), (4, 'z'), (5, 'z')]
没有。在这一点上,我即将手动处理这一切:
>>> vals = {}
>>> vals[0] = lambda: 'a'
>>> vals[1] = lambda: 'b'
……等等。然而,这感觉就像放弃,而且会非常乏味。有没有合适的 Pythonic 方法来完成这项任务?毕竟,我通常喜欢 python 的原因之一是我可以远离手动指针管理;我从没想过我会希望它包含一整套指针工具!