列表理解中的临时变量

时间:2015-04-23 09:58:57

标签: python list-comprehension

我经常遇到一段看起来像这样的代码。

raw_data  = [(s.split(',')[0], s.split(',')[1]) for s in all_lines if s.split(',')[1] != '"NaN"']

基本上,我想知道是否有办法创建一个像splitted_s这样的临时变量,以避免在循环对象上重复操作(比如,在这种情况下,必须拆分它)三次)。

3 个答案:

答案 0 :(得分:9)

如果你有两个处理动作,你可以嵌入另一个列表理解:

raw_data  = [(lhs, rhs) 
            for lhs, rhs 
            in [s.split(',')[:2] for s in all_lines]
            if rhs != '"NaN"']

你可以在里面使用发电机(它也会带来很小的性能提升):

            in (s.split(',')[:2] for s in all_lines)

它甚至比你的实施更快:

import timeit

setup = '''import random, string;
all_lines = [','.join((random.choice(string.letters),
                    str(random.random() if random.random() > 0.3 else '"NaN"')))
                    for i in range(10000)]'''
oneloop = '''[(s.split(',')[0], s.split(',')[1]) 
              for s in all_lines if s.split(',')[1] != '"NaN"']'''
twoloops = '''raw_data  = [(lhs, rhs) 
                for lhs, rhs 
                in [s.split(',') for s in all_lines]
                if rhs != '"NaN"']'''

timeit.timeit(oneloop, setup, number=1000)  # 7.77 secs
timeit.timeit(twoloops, setup, number=1000) # 4.68 secs

答案 1 :(得分:1)

你不能。

  

列表推导由括号组成,括号中包含一个表达式,后跟一个for子句,然后是零个或多个for或if子句。结果将是一个新的列表,该列表是通过在其后面的for和if子句的上下文中计算表达式而得到的。

From here

Python中的赋值不是表达式。

正如Padraic Cunningham所评论的那样 - 如果你需要多次拆分它,请不要在列表理解中这样做。

答案 2 :(得分:0)

Python 3.8开始并引入assignment expressions (PEP 572):=运算符),可以在列表推导中使用局部变量,以避免两次调用相同的表达式:< / p>

在我们的例子中,如果line.split(',')不等于{{1,则可以使用表达式的结果来过滤列表,同时可以将parts的计算结果命名为变量parts[1]。 }};并因此重新使用NaN来产生映射值:

parts