就地循环到就地列表理解

时间:2016-11-28 23:59:53

标签: python list-comprehension in-place

我想知道是否有办法将上面的代码作为就地列表理解或使用map()(只是for循环):

s = [''] * n
s[0:k] = ['X'] * k
for i in range(k,m): 
    s[i] = foo(s[i-k:i]) 

如果我这样做:

s = [''] * n
s[0:k] = ['X'] * k
s = [foo(s[i-k:i]) for i in range(k,m)]

s将无法正确更新。

2 个答案:

答案 0 :(得分:0)

这里的杀手案例是,如果m> 2 * k,我们得到 foo 作为输入,它在先前的调用中作为输出产生。这意味着我们不能简单地静态地评估 s 并且在已知元素上轻快地迭代 - 在初始评估时s [max(k,n)]之后的元素是未知的,因此那些 foo 的动态数量。

想象一下, foo 会返回依赖于初始值和随机内容的内容;很容易看到从列表的一个部分到另一个部分的传播不能静态工作。例如,让 foo 附加一个随机的十六进制数字,让我们在原始帖子中尝试这两个想法:

import random
def foo(chr_list):
    inventory = "0123456789abcdef"
    return chr_list[0] + random.choice(inventory)

k = 3
m = 10
n = 16
s = [''] * n
s[0:k] = ['X'] * k

print "1 s init", s 
for i in range(k,m): 
    s[i] = foo(s[i-k:i])
print "1 s done", s
print

s = [''] * n
s[0:k] = ['X'] * k
print "2 s init", s
s = [foo(s[i-k:i]) for i in range(k,m)]
print "2 s done", s

输出:

1 s init ['X', 'X', 'X', '', '', '', '', '', '', '', '', '', '', '', '', '']
1 s done ['X', 'X', 'X', 'X7', 'Xd', 'X9', 'X74', 'Xd6', 'X9d', 'X741', '', '', '', '', '', '']

2 s init ['X', 'X', 'X', '', '', '', '', '', '', '', '', '', '', '', '', '']
2 s done ['X8', 'X2', 'X9', 'f', 'd', '0', '7']

总而言之,我不认为值得将其纳入单行内容。

答案 1 :(得分:0)

正如评论所提到的,列表理解始终会创建一个新列表。如果您直接将列表理解结果分配到其中,原始列表将会消失。

您可以将原始列表的切片替换为列表推导的结果,如下所示

# compact initialization into 1 line
s = ['X']*k + [''] * (n-k)
# replace slice of list s from k to m
s[k:m] = [foo(s[i-k:i]) for i in range(k,m)]