隐藏Python中的迭代器行为

时间:2017-11-29 12:09:31

标签: python

所以我正在尝试使用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事情,所以我知道必须缺少 一些愚蠢的事情,但对于我的生活,我无法弄清楚它是什么。

任何接受者?提前谢谢。

1 个答案:

答案 0 :(得分:1)

生成器函数一次又一次地覆盖ctx引用的同一个dict的内容。

在测试代码的第二个变体中,在覆盖之间打印内容,以便可以看到更改。

这可能意味着某种优化不能一直创建新的词典,但显然很危险。