【问题标题】:python question regarding generator and keyword yield关于生成器和关键字yield的python问题
【发布时间】:2019-12-16 21:04:54
【问题描述】:

我是 Python 新手,请多多包涵。 sn-p 来自“Python 食谱”一书,关于如何从不可散列的集合中删除重复数据。

def dedup(items, key=None):
    seen = set()
    for item in items:
        val = item if key is None else key(item)
        if val not in seen:
            yield val
            seen.add(val)

if __name__ == '__main__':
    a = [{'x':1, 'y':2}, {'x':1, 'y':3}, {'x':1, 'y':2}, {'x':2, 'y':4}]
    print(list(dedup(a, key=lambda d:(d['x'],d['y']))))

测试时,根据“key”的定义,结果显示为:

a = [ {'x':1, 'y':2}, {'x':1, 'y':3}, {'x':1, 'y':2}, {'x':2, 'y':4}]
>>> list(dedupe(a, key=lambda d: (d['x'],d['y'])))
[{'x': 1, 'y': 2}, {'x': 1, 'y': 3}, {'x': 2, 'y': 4}]
>>> list(dedupe(a, key=lambda d: d['x']))
[{'x': 1, 'y': 2}, {'x': 2, 'y': 4}]

现在是问题:

  1. dedup函数中,过滤后的结果似乎保存在set中,当item从list移动​​到set时,list的顺序是如何保持的?
  2. 函数中没有使用显式返回语句,是否意味着隐式返回集合“seen”?
  3. 您能解释一下测试中的两个 lambda 定义吗?从结果来看,第一个似乎同时检查了 dict 类型的 k 和 v,而后者只检查了 dict 的键是否重复。

【问题讨论】:

  • 集合seen不返回,对返回东西的顺序没有影响;它纯粹在内部用于检查重复项。

标签: python data-structures lambda generator yield


【解决方案1】:
  1. 您并未将列表物理转换为set,请注意set 仅用于跟踪看到的项目。否则,你只是线性迭代,保持原来的顺序

  2. 不,seen 永远不会返回。我会研究生成器,但要点是yield 将函数转换为生成器,一次为您生成一个值。 list 消耗生成器。 seen 将停留在函数范围内,直到生成器被完全消耗(for 循环退出)

def f():
    seen = set()
    for i in range(3):
        seen.add(i)
        print(seen)
        yield i

list(f())
{0}
{0, 1}
{0, 1, 2}
[0, 1, 2]
  1. 在第一个示例中,您正在过滤成对的项目,并且您不关心键,只关心值,因此将它们存储在一个元组中:
a = set()
d = {'x': 1, 'y': 2}
a.add((d['y'], d['y']))

在第二个示例中,您只关心 x 值,因此您可以通过调用 seen.add(d['x']) 显式添加它。

您可以在 map 中测试您的 lambda 函数,看看它们会产生什么效果:

a = [{'x':1, 'y':2}, {'x':1, 'y':3}, {'x':1, 'y':2}, {'x':2, 'y':4}]

# first
list(map(lambda d: (d['x'], d['y']), a))
[(1, 2), (1, 3), (1, 2), (2, 4)]

# second
list(map(lambda d: d['x'], a))
[1, 1, 1, 2]

或在for 循环中:

# this is bad practice, but it illustrates the point
x = lambda d: d['x']
for val in a:
    print(x(val))
1
1
1
2

【讨论】:

    猜你喜欢
    • 2020-07-05
    • 2011-11-02
    • 1970-01-01
    • 2017-08-03
    • 2021-10-26
    • 2020-04-07
    • 2022-12-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多