python列表循环技术语法

时间:2013-06-18 06:31:21

标签: python list-comprehension

我正在阅读有关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代表x,如果x未见,且未见过.add(x)]

这是什么语法?我怎么看?

谢谢。

3 个答案:

答案 0 :(得分:3)

它被称为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

答案 1 :(得分: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,因此该项目已包含在内,作为副作用,它会被添加到{{1}设置

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

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

seen

答案 2 :(得分:3)

首先,列表推导通常易于阅读,这是一个简单的例子:

[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方法通常会返回None,如果他们修改了数据结构(pop是例外情况之一)

我还注意到当前接受的这种方式(2.7+)更易读并且不使用 hack ,如下所示:

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

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