python - 没有赋值的列表理解

时间:2013-01-10 01:20:43

标签: python list-comprehension

今天我正在使用BeautifulSoup解析一个包含zip文件路径列表的目录索引,并且遇到了一件有趣的事情。让我们假设我想获取我得到的标签的所有href属性并将它们直接放入队列中:

q = Queue.Queue()
[q.put(tag['href']) for tag in soup.findAll('a')]

我从来没有遇到这样的情况,在此之前可以使用内联而不将其分配给任何内容,只是通过一些例程调用生成另一个迭代器。这被认为是不好的做法吗?它本身就是“pythonic”吗?是否有更好的单行将所有项目放入队列?

5 个答案:

答案 0 :(得分:11)

已多次询问此问题,例如herehere。但这是一个有趣的问题。列表推导意味着用于其他事情。

其他选项包括

  1. 使用map() - 与您的示例基本相同
  2. 使用filter() - 如果您的函数返回None,您将获得一个空列表
  3. 只是简单的for - 循环
  4. 虽然普通循环是最好的方法。在这种情况下,它在语义上是正确的,所有其他方式,包括列表理解,滥用概念的副作用。

    在Python 3.x中,map()filter()是生成器,因此在迭代它们之前不执行任何操作。所以我们需要,例如,list(map(...)),这会使情况变得更糟。

答案 1 :(得分:6)

如果你认为它是一个循环覆盖在汤.findAll返回的列表上,它将如下所示:

for tag in soup.findAll('a'):
    q.put(tag['href'])

这可能是更“'pythonic'形式,因为'明确胜于暗示'

答案 2 :(得分:3)

关于这个帖子有很多意见,我只能说我组织的编码惯例。

有许多方法可以影响循环,但列表推导的一个关键属性是它们创建列表,迭代序列中每个都有一个项目。

>>> import Queue
>>> q = Queue.Queue()
>>> [q.put(item) for item in range(5)]
[None, None, None, None, None]
>>>

这个未使用的清单显然是浪费。因此,这种结构,具有未使用的返回值的列表理解;禁止出现在我们的代码库中。像上面这样的显式循环,或者生成与消耗它的东西相结合,例如:

>>> any(q.put(item) for item in xrange(5))
False
>>>

或只是:

>>> for item in xrange(5):
...     q.put(item)
...
>>>

需要通过审核。

答案 3 :(得分:2)

可能不是一个更好的单行,但我(个人)考虑这样做而不是:

for tag in soup.findAll('a'):
    q.put(tag['href'])

是不好的做法。首先,一个班轮将生成一个充满[None]的列表,这可能效率更低。其次,目前还不清楚代码在做什么;看到列表理解通常意味着结果列表将以某种方式使用。

答案 4 :(得分:0)

在最新版本的Python中,您可以按照建议here的方式使用any()

q = Queue.Queue()
any(q.put(tag['href']) for tag in soup.findAll('a'))