所以我正在尝试使用somo Odoo代码(Qweb模板更具体),我发现了这个功能
def foreach_iterator(base_ctx, enum, name):
ctx = base_ctx.copy()
if not enum:
return
if isinstance(enum, int):
enum = xrange(enum)
size = None
if isinstance(enum, Sized):
ctx["%s_size" % name] = size = len(enum)
if isinstance(enum, Mapping):
enum = enum.iteritems()
else:
enum = izip(*tee(enum))
value_key = '%s_value' % name
index_key = '%s_index' % name
first_key = '%s_first' % name
last_key = '%s_last' % name
parity_key = '%s_parity' % name
even_key = '%s_even' % name
odd_key = '%s_odd' % name
for index, (item, value) in enumerate(enum):
ctx[name] = item
ctx[value_key] = value
ctx[index_key] = index
ctx[first_key] = index == 0
if size is not None:
ctx[last_key] = index + 1 == size
if index % 2:
ctx[parity_key] = 'odd'
ctx[even_key] = False
ctx[odd_key] = True
else:
ctx[parity_key] = 'even'
ctx[even_key] = True
ctx[odd_key] = False
yield ctx
# copy changed items back into source context (?)
# FIXME: maybe values could provide a ChainMap-style clone?
for k in base_ctx.keys():
base_ctx[k] = ctx[k]
这个函数是如何实现t-foreach
所以它应该创建一个迭代器而不是传入它。
但是...
>>> list(foreach_iterator({},[1,2,3],"name"))
[{'name': 2,
'name_even': False,
'name_first': False,
'name_index': 1,
'name_last': True,
'name_odd': True,
'name_parity': 'odd',
'name_size': 2,
'name_value': 2},
{'name': 2,
'name_even': False,
'name_first': False,
'name_index': 1,
'name_last': True,
'name_odd': True,
'name_parity': 'odd',
'name_size': 2,
'name_value': 2}]
然后
>>> k = foreach_iterator({},[1,2],"name")
>>> k.next()
{'name': 1,
'name_even': True,
'name_first': True,
'name_index': 0,
'name_last': False,
'name_odd': False,
'name_parity': 'even',
'name_size': 2,
'name_value': 1}
>>> k.next()
{'name': 2,
'name_even': False,
'name_first': False,
'name_index': 1,
'name_last': True,
'name_odd': True,
'name_parity': 'odd',
'name_size': 2,
'name_value': 2}
我已经做了一段时间的Python事情,所以我知道必须缺少 一些愚蠢的事情,但对于我的生活,我无法弄清楚它是什么。
任何接受者?提前谢谢。
答案 0 :(得分:1)
生成器函数一次又一次地覆盖ctx
引用的同一个dict的内容。
在测试代码的第二个变体中,在覆盖之间打印内容,以便可以看到更改。
这可能意味着某种优化不能一直创建新的词典,但显然很危险。