在内联for循环初始化中引用列表?

1 投票
2 回答
3167 浏览
提问于 2025-04-17 17:59

我想写一些像这样的代码:

x = [0]
x = [x[i-1] for i in range(1,10)]

我知道这个例子没有什么实际意义。但我想知道在用这种方式初始化列表时,是否可以使用之前计算过的值。(也许可以用某种lambda表达式)

这是我实际需要的代码:

x = [(b[i] - sum([(a[i][j] * x[j]) for j in range(i)])) / a[i][i] for i in range(n)]

这当然会出现以下错误:

UnboundLocalError: local variable 'x' referenced before assignment

我知道有一种方法可以解决这个问题:

x = []
for i in range(n):                        
    x.append((b[i] - sum([(a[i][j] * x[j]) for j in range(i)])) / a[i][i])  

但我真的很想知道第一个方法是否有可能实现。

2 个回答

4

即使这可能实现,我也觉得你不应该尝试这么做。这个“冗长”的三行解决方案已经相当复杂了,因为里面有嵌套的列表推导,而这还不是那行的外层部分。而且里面还有另一个求和。

我其实会把它拆得更细,把列表推导单独写出来,像这样:

x = []
for i in range(n):
    k = sum(a[i][j] * x[j] for j in range(i))
    x.append((b[i] - k) / a[i][i])

我觉得可能还有办法把它简化得更好,但光看这些代码很难判断,因为我不知道它具体是做什么的,也没有abn的示例数据。

3

虽然我完全同意你想做的事情不是个好习惯,但其实有一种方法可以做到(算是吧)。比如,我们来看这个:

x = [1]
z = [x.append(x[i]*2) for i in range(10)]

现在自然我们会得到:

>>> print z
[None, None, None, None, None, None, None, None, None, None]

但是,x保存了我们想要的值:

>>> print x
[1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]

所以以类似的奇怪方式,你可以这样做:

x = [some_init_value]
[x.append((b[i] - sum([(a[i][j] * x[j]) for j in range(i)])) / a[i][i]) for i in range(n)]

注意,x就地修改的,我们并没有把列表推导的结果赋值给x,因为列表推导会返回一堆None

我想强调的是,这种做法是不好的。好的编程习惯是,列表推导不应该有副作用(就像我们这里的情况)。

编辑:显然在 CPython 版本小于等于 2.6 时,你可以用这种“病态黑客”方法,列表推导会有一个隐藏的值。eryksun 为斐波那契数列提供了一个很棒的黑客方法:

fib = [[0,1][j] if j<2 else locals()['_[1]'][j-1] + locals()['_[1]'][j-2] for j in range(10)]

自然,这在 CPython 2.7 和 PyPy 上是行不通的。

撰写回答