我可以在列表理解中形成列表时使用列表吗?
Can I use a list while forming it in a list comprehension?
例如下面的代码
primeList = []
for val in range(2, num):
if not any(val % i == 0 for i in primeList):
primeList.append(val)
我怎样才能将这段代码转化为列表理解?
不,你不能,因为在理解完成迭代之前,列表不作为 Python 对象存在。您不能引用不存在的对象。老实说,我只想将其保留为 for
循环 - 列表推导并不是替换所有列表构造循环的灵丹妙药。
但是...您可能会变得棘手并使用仅按需评估的生成器。将此与列表的 extend()
方法相结合,该方法在获取元素时将元素添加到列表中(无论如何在我的测试中),您可以在扩展列表时使用正在扩展的列表的当前内容。
# make sure to set `num`
plist = []
plist.extend(c for c in range(2, num) if not any(c % p == 0 for p in plist))
公平警告:据我所知,extend()
在生成元素时将元素添加到列表中的事实不是规范的一部分,因此这段代码是否有效可能取决于实现.但是我在Python 2.7和3.4测试过,每次都得到一个素数列表。
#!/usr/bin/python
from __future__ import print_function
import math
def is_prime(x):
if (x == 0 or x == 1 or x < 0):
return False
for i in range(2, int(math.sqrt(x)) + 1):
if (not (x % i)):
return False
return True
def filter_primes(max):
return [val for val in range(2, max) if is_prime(val)]
def main():
primes = filter_primes(20)
print(primes)
if __name__ == "__main__":
main()
上面的代码从定义一个名为 is_prime(x)
的函数开始,如果 x
是素数,则 returns 为真,否则为假。然后一个名为 filter_primes(max)
的函数使用 is_prime 和列表理解将素数过滤到返回的数组中。范围的最大数量通过 max
指定。主函数只是调用 API 来测试它。
编辑:
但也许我误解了 "turn this exact piece of code into list comprehension" 的意思。根据您 真正 想要做什么,使用生成器是实现动态目的的好主意。
实际上,如果您真的想要,您可以在 列表理解中创建列表的相同副本 并参考它...
primeListCopy = []
primeList = [primeListCopy.append(val) or val for val in range(2, num)
if not any(val % i == 0 for i in primeListCopy)]
这利用了 primeListCopy.append(val) or val
求值为 val
的事实,因为对列表 returns None
和 or
的赋值求值为右侧值。
这在性能方面肯定比简单的 for-loop
更差。我写这篇文章是为了回应 OP 的问题 "what could be the closest mimic when i had nothing but list comprehension. ( this is not a development code, just my experiments)"
也就是说,额外的工作仅 增加了 O(n) 的工作量,因此实际上并没有增加循环的算法复杂性。可以想象(虽然不太可能)列表理解优化将使它比原来的 for 循环更快。
例如下面的代码
primeList = []
for val in range(2, num):
if not any(val % i == 0 for i in primeList):
primeList.append(val)
我怎样才能将这段代码转化为列表理解?
不,你不能,因为在理解完成迭代之前,列表不作为 Python 对象存在。您不能引用不存在的对象。老实说,我只想将其保留为 for
循环 - 列表推导并不是替换所有列表构造循环的灵丹妙药。
但是...您可能会变得棘手并使用仅按需评估的生成器。将此与列表的 extend()
方法相结合,该方法在获取元素时将元素添加到列表中(无论如何在我的测试中),您可以在扩展列表时使用正在扩展的列表的当前内容。
# make sure to set `num`
plist = []
plist.extend(c for c in range(2, num) if not any(c % p == 0 for p in plist))
公平警告:据我所知,extend()
在生成元素时将元素添加到列表中的事实不是规范的一部分,因此这段代码是否有效可能取决于实现.但是我在Python 2.7和3.4测试过,每次都得到一个素数列表。
#!/usr/bin/python
from __future__ import print_function
import math
def is_prime(x):
if (x == 0 or x == 1 or x < 0):
return False
for i in range(2, int(math.sqrt(x)) + 1):
if (not (x % i)):
return False
return True
def filter_primes(max):
return [val for val in range(2, max) if is_prime(val)]
def main():
primes = filter_primes(20)
print(primes)
if __name__ == "__main__":
main()
上面的代码从定义一个名为 is_prime(x)
的函数开始,如果 x
是素数,则 returns 为真,否则为假。然后一个名为 filter_primes(max)
的函数使用 is_prime 和列表理解将素数过滤到返回的数组中。范围的最大数量通过 max
指定。主函数只是调用 API 来测试它。
编辑: 但也许我误解了 "turn this exact piece of code into list comprehension" 的意思。根据您 真正 想要做什么,使用生成器是实现动态目的的好主意。
实际上,如果您真的想要,您可以在 列表理解中创建列表的相同副本 并参考它...
primeListCopy = []
primeList = [primeListCopy.append(val) or val for val in range(2, num)
if not any(val % i == 0 for i in primeListCopy)]
这利用了 primeListCopy.append(val) or val
求值为 val
的事实,因为对列表 returns None
和 or
的赋值求值为右侧值。
这在性能方面肯定比简单的 for-loop
更差。我写这篇文章是为了回应 OP 的问题 "what could be the closest mimic when i had nothing but list comprehension. ( this is not a development code, just my experiments)"
也就是说,额外的工作仅 增加了 O(n) 的工作量,因此实际上并没有增加循环的算法复杂性。可以想象(虽然不太可能)列表理解优化将使它比原来的 for 循环更快。