将带有赋值的循环转换为推导式 [英] Converting a loop with an assignment into a comprehension
问题描述
将循环转换为推导式非常简单:
Converting a loop into a comprehension is simple enough:
mylist = []
for word in ['Hello', 'world']:
mylist.append(word.split('l')[0])
到
mylist = [word.split('l')[0] for word in ['Hello', 'world']]
但是当循环涉及为引用赋值时,我不确定如何继续.
But I'm not sure how to proceed when the loop involves assigning a value to a reference.
mylist = []
for word in ['Hello', 'world']:
split_word = word.split('l')
mylist.append(split_word[0]+split_word[1])
理解最终看起来像这样:
And the comprehension ends up looking like this:
mylist = [word.split('l')[0]+word.split('l')[1] for word in ['Hello', 'world']]
这会多次计算 word.split('l')
而循环只计算一次并保存引用.我尝试了以下方法:
This calculates word.split('l')
multiple times whereas the loop only calculates it once and saves a reference. I've tried the following:
mylist = [split_word[0]+split_word[1] for word in ['Hello', 'world'] with word.split('l') as split_word]
失败是因为 with
不能那样工作,并且:
which fails because with
doesn't work that way, and:
mylist = [split_word[0]+split_word[1] for word in ['Hello', 'world'] for split_word = word.split('l')]
这也不起作用.我知道通过 *
和 **
解包,但我不确定它适合这里的位置.是否有可能将这些类型的循环转化为理解,希望以一种整洁的方式?
which doesn't work either. I'm aware of unpacking via *
and **
but I'm not sure where that would fit in here. Is it possible to turn these sorts of loops into comprehensions, hopefully in a tidy way?
推荐答案
您不能直接将该循环转换为推导式.推导式是表达式,只能包含表达式,赋值是语句.
You can't directly translate that loop to a comprehension. Comprehensions, being expressions, can only contain expressions, and assignments are statements.
然而,这并不意味着没有选择.
However, that doesn't mean there are no options.
首先,以调用 split
两次为代价,你可以这样做:
First, at the cost of calling split
twice, you can just do this:
mylist = [word.split('l')[0]+word.split('l')[1] for word in ['Hello', 'world']]
但是您不想调用 split
两次.
But you don't want to call split
twice.
最通用的方法是使用一系列生成器表达式(最后是一个列表推导式)来转换事物:
The most general way around that is to use a chain of generator expressions (with one list comprehension at the end) to transform things:
words = (word.split('l') for word in ['Hello', 'world'])
mylist = [w[0]+w[1] for w in words]
如果您真的想将所有内容合并为一个表达式,您可以:
If you really want to merge that all into one expression, you can:
mylist = [w[0]+w[1] for w in
(word.split('l') for word in ['Hello', 'world'])]
但除非您确实需要在表达式中使用它,否则不这样做可能更具可读性.
But unless you actually need it to be in an expression, it's probably more readable not to do that.
在这种情况下,更具体的方法是将 w[0]+w[1]
替换为不需要引用 w
两次的等效内容:
A more specific way in this case is to replace the w[0]+w[1]
with something equivalent that doesn't need to reference w
twice:
mylist = [''.join(word.split('l')[:2]) for word in ['Hello', 'world']]
你也可以概括这一点.您可以将 any 表达式转换为函数,这意味着您可以通过将其作为参数传递给该函数来避免评估它的任何部分.如果没有可以执行您想要的功能的函数,请编写它:
And you can always generalize this one, too. You can turn any expression into a function, which means you can avoid evaluating any part of it by passing it as an argument to that function. If there isn't a function that does what you want, write it:
def join_up(split_word):
return split_word[0]+split_word[1]
mylist = [join_up(word.split('l')) for word in ['Hello', 'world']]
如果你需要在不重复任何工作的情况下将所有内容整合到一个表达式中,那可能不太好:
If you need to make that all into one expression without repeating any work, it may not be pretty:
mylist = [(lambda split_word: split_word[0]+split_word[1])(word.split('l'))
for word in ['Hello', 'world']]
<小时>
但最终,除非我已经有一个函数可以满足我的需要,否则我会使用生成器表达式链解决方案.
But ultimately, unless I already had a function lying around that did what I needed, I'd use the chain-of-generator-expressions solution.
或者,当然,只是将其保持在显式循环中;for
循环没有任何问题,如果中间临时变量使您的代码更清晰,那么没有比使用赋值语句更好的方法了.
Or, of course, just keep it in an explicit loop; there's nothing wrong with for
loops, and if the intermediate temporary variable makes your code clearer, there's no better way to do that than with an assignment statement.
这篇关于将带有赋值的循环转换为推导式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!