【问题标题】:python list looping technique syntax [duplicate]python列表循环技术语法[重复]
【发布时间】:2013-06-14 06:15:26
【问题描述】:

我正在阅读关于 python 删除列表中重复元素的article。 有一个函数定义为:

def f8(seq): # Dave Kirby
    # Order preserving
    seen = set()
    return [x for x in seq if x not in seen and not seen.add(x)]

但是,我不太了解 [x for x in seq if x not in seen and not seen.add(x)]

这是什么语法?怎么读?

谢谢。

【问题讨论】:

标签: python list-comprehension


【解决方案1】:

首先,列表推导式通常很容易阅读,这里有一个简单的例子:

[x for x in seq if x != 2]

翻译为:

result = []
for x in seq:
    if x != 2:
        result.append(x)

您无法阅读此代码的原因是因为它不是我所说的in this question 的可读和hacky 代码:

def f8(seq):
    seen = set()
    return [x for x in seq if x not in seen and not seen.add(x)]

翻译为:

def f8(seq):
    seen = set()
    result = []
    for x in seq:
        if x not in seen and not seen.add(x): # not seen.add(...) always True
            result.append(x)

并且依赖于set.add 是一个始终返回None 的就地方法这一事实,因此not None 的计算结果为True

>>> s = set()
>>> y = s.add(1) # methods usually return None
>>> print s, y
set([1]) None

之所以这样编写代码,是为了偷偷利用 Python 的列表理解速度优化。

如果 Python 方法修改数据结构,通常会返回 Nonepop 是例外之一)

我还注意到,目前公认的这样做的方式 (2.7+) 更具可读性并且不使用 hack,如下所示:

>>> from collections import OrderedDict
>>> items = [1, 2, 0, 1, 3, 2]
>>> list(OrderedDict.fromkeys(items))
[1, 2, 0, 3]

字典键必须是唯一的,因此会过滤掉重复项。

【讨论】:

  • 新方法的效率和hacky一样吗?
  • @user2213606 效率,是的,我相信它的原始速度没有那么快。然而它更简洁
  • list(OrderedDict.fromkeys(items)) 可移植到 Python3
  • @gnibbler 好点,出于某种原因,我假设它会返回一个列表,因为它保持秩序,但这个 KeysView 也可以
  • +1 很好的解释。
【解决方案2】:

它被称为list comprehension,它们提供了一种语法上更紧凑、更高效的方式来编写基于普通 for 循环的解决方案。

def f8(seq): # Dave Kirby
    # Order preserving
    seen = set()
    return [x for x in seq if x not in seen and not seen.add(x)]

上面的列表推导大致相当于:

def f8(seq):
    seen = set()
    lis =[]
    for x in seq:
        if x not in seen:
            lis.append(x)
            seen.add(x)
    return lis

【讨论】:

    【解决方案3】:

    该构造称为列表推导式 [x for x in seq if some_condition]。在这种情况下,条件是x 不在结果列表中。您无法在运行时检查列表推导的结果,因此它使用名为 seen

    的集合来跟踪其中的项目

    这里的这个条件有点棘手,因为它依赖于副作用

    not in seen and not seen.add(x)
    

    seen.add() 总是返回 None。如果项目 可见,

    not in seenFalse,所以 and 短路了。

    如果项目没有可见,

    not in seenTruenot seen.add(x) 也是 True,因此包含该项目,并且作为副作用,它被添加到 seen 集合中

    虽然这类事情可能很有趣,但这并不是表达意图的特别清晰的方式。

    我认为不那么棘手的方式更具可读性

    def f8(seq):
        seen = set()
        result = []
        for x in seq:
            if x not in seen:
                result.append(x)
                seen.add(x)
        return result
    

    【讨论】:

      猜你喜欢
      • 2013-07-30
      • 2020-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-23
      • 2021-11-20
      相关资源
      最近更新 更多