我的意图是创建一个字典,其中包含哪些键是基元,其值是否为返回字符串的零参数函数。 (这是实施VM的较大项目的一部分。)这些功能中的某些功能并不重要,并且可以手动创建和分配。那些工作很好。然而,其他人似乎适合自动生成。如何强制python3传递值?
我第一次尝试失败:
>>> 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')]
OK,罚款; 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。深度复制不能解决这个问题。结果,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的原因之一是我远离手动指针管理;我从未想到我希望它包含一整套指针工具!
谢谢!设置默认参数对于我来说比通过make_const函数提供所有内容更重要,至少就我对它的工作原理的理解而言。我不认为这两种方法在性能上有任何显着差异? – coriolinus 2012-04-06 12:08:07
@coriolinus不应有任何显着差异。如果有的话,在成为瓶颈之前可能有很多大的鱼要炒。在这一点上,你可能应该咬紧牙关,让你的代码[RPython](http://morepypy.blogspot.de/2011/04/tutorial-writing-interpreter-with-pypy.html),然后编译C,一个JIT编译器和一系列好的GC几乎免费。 – delnan 2012-04-06 12:37:50