Python中迭代之间状态可变的列表理解
我有一些东西非常像Python中的列表理解,只是它在迭代之间共享可变状态。有没有办法用列表来理解Python中迭代之间状态可变的列表理解,python,python-2.7,list-comprehension,Python,Python 2.7,List Comprehension,我有一些东西非常像Python中的列表理解,只是它在迭代之间共享可变状态。有没有办法用列表来理解 def f(x): """ 5-bit LFSR """ return (x >> 1) ^ (0x12*(x&1)) def batch(f, x, n): result = [x] for _ in xrange(1,n): x = f(x) result.append(x) return result
def f(x):
""" 5-bit LFSR """
return (x >> 1) ^ (0x12*(x&1))
def batch(f, x, n):
result = [x]
for _ in xrange(1,n):
x = f(x)
result.append(x)
return result
batch(f, 1, 5)
返回[1,18,9,22,11]
。这里重要的是batch
函数,而不是f(x)
,这里只是一个简单的例子来说明这个问题
或者,我可以使用生成器实现:
def batch(f, x, n):
yield x
for _ in xrange(1,n):
x = f(x)
yield x
list(batch(f, 1, 5))
但闻起来有点难闻。我要找的是这样的东西
batch = [??? for _ in xrange(n)]
batch = [??? for _ in xrange(n)]
不。故意不。最终他们加入了
itertools.acculate
,这是最接近官方推荐的以函数方式实现重复关系的方法,但在2.7中并不存在。如果需要,您可以从中复制“大致相当于”Python实现。您可以在一行中执行此操作,例如使用reduce
(或Python 3中的functools.reduce
):
但这不仅丑陋,而且效率低下,因为它会在每次迭代中创建一个新列表。或者以与Stefan方法类似的方式,不创建中间列表:
>>> functools.reduce(lambda lst, _: lst.append(f(lst[-1])) or lst, range(1, n), [x])
[1, 18, 9, 22, 11]
或者,正如在另一个答案中已经暗示的那样,您可以使用itertools.acculate
,这要好得多,但仍然有点误用,因为它实际上需要一个二进制函数,而在这里,除了第一个值外,我们既不使用第二个参数,也不使用传递到函数中的实际iterable
>>> list(itertools.accumulate([x] * n, lambda y, _: f(y)))
[1, 18, 9, 22, 11]
有没有办法用列表来理解
def f(x):
""" 5-bit LFSR """
return (x >> 1) ^ (0x12*(x&1))
def batch(f, x, n):
result = [x]
for _ in xrange(1,n):
x = f(x)
result.append(x)
return result
batch(f, 1, 5)
我要找的是这样的东西
batch = [??? for _ in xrange(n)]
batch = [??? for _ in xrange(n)]
当然,没问题:
>>> x = 1
>>> n = 5
>>> [prev.append(f(prev[0])) or prev.pop(0) for prev in [[x]] for _ in xrange(n)]
[1, 18, 9, 22, 11]
注意:这是个坏主意。(我这么做几乎只是因为用户2357112说没有办法)如果我能理解的话,这闻起来有点像那些讨厌的Haskell单子中的一个会有用。“除了它在迭代之间共享可变状态。有没有任何方法可以通过列表理解来实现它”可能有一些黑客的方法,但是如果它涉及到变异状态,那么它可能不应该是一个列表理解。同样,“在迭代之间共享可变状态”听起来不像Haskell中的任何东西。不,但是有状态的monads做了。你可以使用<代码>从<代码>中获得的收益来定义递归生成器。天哪,这是鬼鬼祟祟的。虽然这可能是最干净的,我见过的列表理解中状态变量的最佳封装形式(至少在Python3上,状态变量没有泄漏到周围的范围中),我没有发布这样的内容仍然有一个原因:这种代码的每一个实例都在堆栈溢出上,获得了更新投票,增加了人们认为这类事情是个好主意并在代码中实际使用它的风险。@user2357112现在更好了吗?:-)@juanpa.arrivillaga刚刚想出了另一个简洁的方法,它只是没有结尾处带有
xrange
的所需格式:[q.append(f(x))或x代表q in[[x]]代表x in q if len(q)有点晚了,但是有没有人能知道为什么使用这样的代码会是不好的做法?我考虑使用<代码>迭代器。累积< /COD>这是丑陋的,递归关系被明确地列为示例代码中的用例。@斯蒂芬波奇曼好点,固定的,但这使得它更丑。如果你遵循文档,你会使用repeat(x,n)
。既然你愿意创建一个列表,你可以简单地使用[x]*n
。对于reduce
你也可以使用lst.\uu iadd_uf(lst[-1])
,尽管我更喜欢append
+或lst
(尽管它长了三个字符!:-)哈,怎么样:reduce(lambda lst,:lst.append(f(lst[-1])或lst,[[x]]*n)
。我真的笑了这一个…使用常见的[[x]]*n
2D列表得到了…但这里没问题,因为重复的引用被忽略了…我认为这很漂亮。