在那个问题上,我一直在摸不着头脑.
我有一个嵌套列表格式:
( (value1, value2, value3), (value1, value2, value3), ... (value1, value2, value3))
Run Code Online (Sandbox Code Playgroud)
现在我想把它归结为:
( (value1, value2), (value1, value2), ... (value1, value2))
Run Code Online (Sandbox Code Playgroud)
简而言之,尝试删除每个嵌套列表的第3个元素.
这是否可以直接在Python中实现?
您只需使用列表解析即可完成此操作:
>>> x = [(1, 2, 3), (1, 2, 3), (1, 2, 3)]
>>> x = [(a, b) for (a, b, c) in x]
[(1, 2), (1, 2), (1, 2)]
Run Code Online (Sandbox Code Playgroud)
使用列表理解:
outerlist = [sublist[:-1] for sublist in outerlist]
Run Code Online (Sandbox Code Playgroud)
这使用切片来删除每个包含的子列表的最后一个元素.
以上创造了一个list(),而不是一个tuple(); 以下将再次创建一个元组:
outertuple = tuple(sublist[:-1] for sublist in outertuple)
Run Code Online (Sandbox Code Playgroud)
切片子列表比解包和重新打包元组需要更少的操作码,更快地获得结果.
使用元组进行演示:
>>> outertuple = ((1, 2, 3), (4, 5, 6), (7, 8, 9))
>>> tuple(sublist[:-1] for sublist in outertuple)
((1, 2), (4, 5), (7, 8))
Run Code Online (Sandbox Code Playgroud)
使用列表演示:
>>> outerlist = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> [sublist[:-1] for sublist in outerlist]
[[1, 2], [4, 5], [7, 8]]
Run Code Online (Sandbox Code Playgroud)
最后但并非最不重要的是,列表推导的内部循环的字节码反汇编表明切片使用的操作码比解包和重新打包更少:
>>> import dis
>>> def foo(x): return [sublist[:-1] for sublist in x]
...
>>> def bar(x): return [(a, b) for (a, b, c) in x]
...
>>> dis.dis(foo)
1 0 BUILD_LIST 0
3 LOAD_FAST 0 (x)
6 GET_ITER
>> 7 FOR_ITER 16 (to 26)
10 STORE_FAST 1 (sublist)
13 LOAD_FAST 1 (sublist)
16 LOAD_CONST 1 (-1)
19 SLICE+2
20 LIST_APPEND 2
23 JUMP_ABSOLUTE 7
>> 26 RETURN_VALUE
>>> dis.dis(bar)
1 0 BUILD_LIST 0
3 LOAD_FAST 0 (x)
6 GET_ITER
>> 7 FOR_ITER 27 (to 37)
10 UNPACK_SEQUENCE 3
13 STORE_FAST 1 (a)
16 STORE_FAST 2 (b)
19 STORE_FAST 3 (c)
22 LOAD_FAST 1 (a)
25 LOAD_FAST 2 (b)
28 BUILD_TUPLE 2
31 LIST_APPEND 2
34 JUMP_ABSOLUTE 7
>> 37 RETURN_VALUE
Run Code Online (Sandbox Code Playgroud)
11对14操作码.这是一个额外的UNPACK_SEQUENCE和两个以上的STORE_FAST操作码,以及一个BUILD_TUPLE操作码与SLICE+2.
这些差异使拆包和打包变得相当慢:
>>> import timeit
>>> test = [(42, 69, 180) for _ in xrange(1000)]
>>> timeit.timeit('f(x)', 'from __main__ import test as x, foo as f', number=10000)
1.1722910404205322
>>> timeit.timeit('f(x)', 'from __main__ import test as x, bar as f', number=10000)
1.6375460624694824
Run Code Online (Sandbox Code Playgroud)