如何理解python_如何理解python中的列表理解?

列表理解的要点是生成一个结果值列表,每个源值一个(或者每个匹配源值的一个,如果您有if子句)。在

换言之,它与map(或者是map和{}调用链,如果有多个子句的话),只是可以将每个新值描述为旧值的表达式,而不必将其包装在函数中。在

你不能把一个语句(比如mysum = mysum + i)放入理解中,而只能放在表达式中。而且,即使你能想出一个有你想要的副作用的表达,那仍然是一个令人困惑的误用理解。如果不需要结果值的列表,则不要使用列表理解。在

如果您只是尝试在循环中执行计算,请编写一个显式的for循环。在

如果您真的需要它是一行,您可以随时这样做:for i in [i for i in range(2, 10) if i%2==0 or i%5==0]: mysum += i

构建一个清单,用一个理解循环;在for循环中计算副作用y。在

(当然,这是假设您已经在mysum中添加了一些值,例如,使用mysum = 0。)

而且,一般来说,当你想要一个仅仅循环一次的理解时,你想要的理解是一个生成器表达式,而不是一个列表理解。所以,把这些方括号变成括号,你会得到:

^{pr2}$

不过,不管怎样,这两行文字更具可读性和Python风格:for i in (i for i in range(2, 10) if i%2==0 or i%5==0):

mysum += i

…甚至三个:not2or5 = (i for i in range(2, 10) if i%2==0 or i%5==0)

for i in not2or5:

mysum += i

如果您的语言使reduce/fold比循环更直观,那么Python有一个reduce函数。然而,仅仅使用它来消除for循环并将块语句转换为一个行程序,通常不被认为是Pythonic。在

更一般地说,在Python中,试图把东西塞进一行通常会使内容的可读性降低,而不是更多,这通常意味着您需要键入更多的字符和要处理的标记,这远远抵消了节省行所带来的任何收益。在

当然,在这个特定的例子中,您真正想做的就是将一个列表的值求和。而这正是sum所做的。这很难理解。所以:mysum += sum(i for i in range(2, 10) if i%2==0 or i%5==0)

(同样,这是假设您已经在mysum中有要添加的内容。如果不是,只需将+=改为=。后面的例子也是如此,所以我不再解释了。)

尽管如此,我可能会将其写为显式嵌套块:for i in range(2, 10):

if i%2==0 or i%5==0:

mysum += i

…或作为迭代器转换的序列(在本例中实际上只是一个转换):not2or5 = (i for i in range(2, 10) if i%2==0 or i%5==0)

mysum += sum(not2to5)

以这种方式拆分代码是没有代价的(只要使用生成器表达式而不是列表理解),而且它通常会使代码的意图更加明显。在

有关生成器表达式的进一步解释:

生成器表达式与列表理解类似,只是它构建迭代器而不是列表。在某些函数式语言中只能使用“一次迭代”。(通常,这不是问题。在上面所有的例子中,我们唯一要做的就是将它传递给sum函数或在for循环中使用它,然后我们就再也不会引用它了。)当您迭代它时,每个值都是按需构造的,然后在到达下一个值之前释放。在

这意味着空间复杂度是恒定的,而不是线性的。你一次只能在内存中有一个值,而在一个列表中,你显然已经得到了所有的值。这通常是一个巨大的胜利。在

然而,时间复杂度不变。列表理解预先完成了所有的工作,所以它是线性时间来构建,然后免费使用。生成器表达式在您迭代它时执行工作,因此它是free构建,然后线性使用。不管怎样,同一时间。(实际上,由于缓存/内存局部性、流水线等原因,生成器表达式实际上可以快得多,更不用说避免了所有内存移动和分配开销。另一方面,对于一般情况,它的速度较慢,至少在CPython中是这样,因为它必须通过完整的迭代器协议,而不是列表的快速特殊大小写。)

(我在这里假设每一步的功是常数,显然[sum(range(i)) for i in range(n)]是n的二次方的,不是线性的…)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值