线
a[:] = [i + 6 for i in a]
不会节省任何内存。如语言文档中所述,Python会首先评估右侧:
赋值语句评估表达式列表(请记住,它可以是单个表达式或逗号分隔的列表,后者产生一个元组),并将单个结果对象从左到右分配给每个目标列表。
在当前情况下,单个结果对象将是一个新列表,而目标列表中的单个目标将是a[:]
。
我们可以用生成器表达式代替列表推导:
a[:] = (i + 6 for i in a)
现在,右侧将求值为生成器,而不是列表。基准测试表明,这仍然比天真慢
a = [i + 6 for i in a]
那么生成器表达式实际上可以节省任何内存吗?乍一看,您可能会认为确实如此。但是深入研究该函数list_ass_slice()
的源代码表明事实并非如此。线
v_as_SF = PySequence_Fast(v, "can only assign an iterable");
使用PySequence_Fast()首先将可迭代对象(在这种情况下为生成器)转换为元组,然后将其复制到旧列表中。元组使用与列表相同的内存量,因此在这种情况下,使用生成器表达式与使用列表推导基本上相同。在最后一次复制期间,原始列表的项目被重用。