[英]python - list comprehension without assignment
Today I was parsing a directory index with a list of paths to zip files using BeautifulSoup and came across an interesting thing.今天,我正在使用 BeautifulSoup 解析带有 zip 文件路径列表的目录索引,并遇到了一件有趣的事情。 Let's assume I would like to take all the
href
properties of the tags I got and put them directly into a Queue:假设我想获取我获得的标签的所有
href
属性并将它们直接放入队列中:
q = Queue.Queue()
[q.put(tag['href']) for tag in soup.findAll('a')]
I've never run into a situation like this before where a comprehension could be used inline without assigning it to anything, just to generated another iterator through some routine call.我以前从未遇到过这样的情况,可以内联使用推导式而不将其分配给任何东西,只是为了通过一些例行调用生成另一个迭代器。 Is this considered bad practice?
这被认为是不好的做法吗? Is it "pythonic", per se?
它本身是“pythonic”吗? Was there a better one-liner to put all the items into the queue?
是否有更好的单线将所有物品放入队列中?
This has been asked many times, eg, here and here .这已被多次询问,例如, here和here 。 But it's an interesting question, though.
不过,这是一个有趣的问题。 List comprehensions are meant to be used for something else.
列表推导式旨在用于其他用途。
Other options include其他选项包括
map()
- basically the same as your samplemap()
- 与您的示例基本相同filter()
- if your function returns None, you will get an empty listfilter()
- 如果你的函数返回 None,你会得到一个空列表for
-loopfor
循环while the plain loop is the preferable way to do it.而普通循环是最好的方法。 It is semantically correct in this case, all other ways, including list comprehension, abuse concepts for their side-effect.
在这种情况下,它在语义上是正确的,所有其他方式,包括列表理解,滥用概念的副作用。
In Python 3.x, map()
and filter()
are generators and thus do nothing until you iterate over them.在 Python 3.x 中,
map()
和filter()
是生成器,因此在迭代它们之前什么都不做。 So we'd need, eg, a list(map(...))
, which makes it even worse.所以我们需要,例如,一个
list(map(...))
,这让它变得更糟。
If you think of it as a loop over the list returned by soup.findAll it would look like this:如果你把它看作是对 sounding.findAll 返回的列表的循环,它看起来像这样:
for tag in soup.findAll('a'):
q.put(tag['href'])
This is probably the more 'pythonic' form as 'explicit is better than implict'这可能是更“pythonic”的形式,因为“显式优于隐式”
There are many opinions on this thread, I can only speak from coding conventions at my organization.关于这个线程有很多意见,我只能从我组织的编码约定中发言。
there are many ways to affect a loop, but a key attribute of list comprehensions is that they create lists , with one item for each in the iterated over sequence.有很多方法可以影响循环,但列表推导式的一个关键属性是它们创建列表,在迭代序列中每个列表都有一个项目。
>>> import Queue
>>> q = Queue.Queue()
>>> [q.put(item) for item in range(5)]
[None, None, None, None, None]
>>>
this unused list is obviously wasteful.这个未使用的列表显然是浪费的。 As such, this construction, a list comprehension with unused return value;
因此,这个结构是一个带有未使用返回值的列表推导式; is forbidden from appearing in our code base.
禁止出现在我们的代码库中。 An explicit loop like above, or a generated combined with something that consumes it, for instance:
像上面这样的显式循环,或者生成的与消耗它的东西相结合,例如:
>>> any(q.put(item) for item in xrange(5))
False
>>>
or just:要不就:
>>> for item in xrange(5):
... q.put(item)
...
>>>
is required to pass review.需要通过审核。
Probably not a better one-liner, but I'd (personally) consider doing this instead of:可能不是更好的单线,但我(个人)考虑这样做而不是:
for tag in soup.findAll('a'):
q.put(tag['href'])
to be bad practice.是不好的做法。 Firstly, the one liner will generate a list full of
[None]
, which is likely more inefficient.首先,one liner 将生成一个充满
[None]
的列表,这可能效率更低。 Secondly, it's not immediately clear what the code is doing;其次,不能立即清楚代码在做什么; seeing a list comprehension generally implies the resultant list will be used in some way.
看到列表推导式通常意味着将以某种方式使用结果列表。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.