列表理解中的临时变量
Temporary variable within list comprehension
我经常遇到这样一段代码。
raw_data = [(s.split(',')[0], s.split(',')[1]) for s in all_lines if s.split(',')[1] != '"NaN"']
基本上,我想知道是否有办法创建一个像 splitted_s
这样的临时变量,以避免必须对循环对象重复操作(例如,在这种情况下,必须分成三份)。
如果你有两个动作要处理,你可以嵌入另一个列表理解:
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
你不能。
A list comprehension consists of brackets containing an expression followed by a for clause, then zero or more for or if clauses. The result will be a new list resulting from evaluating the expression in the context of the for and if clauses which follow it.
Python 中的赋值不是表达式。
正如 Padraic Cunningham 评论的那样 - 如果您需要多次拆分它,请不要在列表理解中这样做。
开始 Python 3.8
,并引入 assignment expressions (PEP 572)(:=
运算符),可以在列表理解中使用局部变量以避免调用两次相同的表达式:
在我们的例子中,如果 parts[1]
不等于 [,我们可以将 line.split(',')
的评估命名为变量 parts
,同时使用表达式的结果来过滤列表=16=];从而重新使用 parts
来生成映射值:
# lines = ['1,2,3,4', '5,NaN,7,8']
[(parts[0], parts[1]) for line in lines if (parts := line.split(','))[1] != 'NaN']
# [('1', '2')]
我经常遇到这样一段代码。
raw_data = [(s.split(',')[0], s.split(',')[1]) for s in all_lines if s.split(',')[1] != '"NaN"']
基本上,我想知道是否有办法创建一个像 splitted_s
这样的临时变量,以避免必须对循环对象重复操作(例如,在这种情况下,必须分成三份)。
如果你有两个动作要处理,你可以嵌入另一个列表理解:
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
你不能。
A list comprehension consists of brackets containing an expression followed by a for clause, then zero or more for or if clauses. The result will be a new list resulting from evaluating the expression in the context of the for and if clauses which follow it.
Python 中的赋值不是表达式。
正如 Padraic Cunningham 评论的那样 - 如果您需要多次拆分它,请不要在列表理解中这样做。
开始 Python 3.8
,并引入 assignment expressions (PEP 572)(:=
运算符),可以在列表理解中使用局部变量以避免调用两次相同的表达式:
在我们的例子中,如果 parts[1]
不等于 [,我们可以将 line.split(',')
的评估命名为变量 parts
,同时使用表达式的结果来过滤列表=16=];从而重新使用 parts
来生成映射值:
# lines = ['1,2,3,4', '5,NaN,7,8']
[(parts[0], parts[1]) for line in lines if (parts := line.split(','))[1] != 'NaN']
# [('1', '2')]