Python:访问列表,因为它被理解

时间:2015-11-05 23:29:01

标签: python python-3.x list-comprehension

有没有办法访问列表,因为它被理解?特别是我想再次对已添加的元素进行迭代。

例如,我正在寻找类似的东西:

[x for x in range(foo) if x not in self]

[x for x in range(foo) if any(y for y in self)]

其中self将是刚刚理解的列表本身。

2 个答案:

答案 0 :(得分:5)

简而言之:不,你不能这样做。 Python的列表推导(以及像生成器表达式这样的相关结构)并不像Haskell的懒惰列表那样强大(它可以做你想要的)。语法类似,但Python不是纯粹的函数式语言,具有惰性递归评估作为语法特性;它的翻译不够复杂,无法理解和处理这样的行为。

更复杂的答案:你可以通过滥用列表理解(例如,acushner的答案中使用的set更新黑客)在特定情况下破解它。但是列表推导通常应该努力成为现有数据的转换和过滤器;他们不应该通过副作用执行其他工作,因为它会使代码更加复杂,使维护者感到困惑。列表理解是一种功能模式;副作用明显不起作用,因此人们不会寻找或期待它们。如果你需要做这样的事情,编写一个能够隔离复杂性并保持跟踪目前产生的值的内部状态的函数(可能是生成器函数)会更好。 itertools recipes中提供的各种无条件配方就是一个很好的例子。

获得相当高级:Haskell可以做到这一点,因为它的列表推导可以是懒惰的,但可以重用(它有内存)。因此,哈斯克尔可以吃它的蛋糕并吃掉它;列表可以根据先前的元素定义元素,因为这些元素将在需要时生成,并且可以多次读取。 Python将懒惰与可重用性区分开来。热切地评估列表理解;它完成之前填充它实际上绑定到一个可以用来访问它的名称(所以它不能在构建它时从中间列表中读取值)。一个生成器表达式大部分都是懒惰的(它将可迭代的迭代绑定,但其他一切都是懒惰的)所以当它被评估时,它可能绑定到一个名称,但它没有内存;你不能使用genexpr中genexpr的值,因为这样做必然会推进生成器(在大多数情况下我可以想到,导致无限递归,因为它试图根据下一个重复定义下一个结果结果,一遍又一遍)。

答案 1 :(得分:1)

首先,newDice = quietRoll() while newDice not in (7, firstRoll): newDice = quietRoll() if newDice == firstRoll: return 1 if newDice == 7: return 0 只是any(y for y in self)

第二,你的功能不会做任何事情。你有效写的是:

any(self)

这只是一个空列表。

你想要的是res = [] for x in range(foo): if any(res): res.append(x)

set

如果您关心订单,可以执行以下操作:

res = set(values)