简体   繁体   English

在python中深度复制生成器

[英]deep-copying a generator in python

I'm using a generator function, say: 我正在使用发电机功能,说:

def foo():
    i=0
    while (i<10):
         i+=1
         yield i

Now, I would like the option to copy the generator after any number of iterations, so that the new copy will retain the internal state (will have the same 'i' in the example) but will now be independent from the original (ie iterating over the copy should not change the original). 现在,我希望选择在任意次数的迭代后复制生成器,以便新副本将保留内部状态(在示例中将具有相同的“i”),但现在将独立于原始状态(即迭代)副本不应该改变原来的)。

I've tried using copy.deepcopy but I get the error: 我尝试过使用copy.deepcopy但是我收到错误:

 "TypeError: object.__new__(generator) is not safe, use generator.__new__()"   

Obviously, I could solve this using regular functions with counters for example. 显然,我可以使用带有计数器的常规函数​​来解决这个问题。 But I'm really looking for a solution using generators. 但我真的在寻找使用发电机的解决方案。

There are three cases I can think of: 我能想到三种情况:

  • Generator has no side effects, and you just want to be able to walk back through results you've already captured. 生成器没有副作用,您只希望能够回顾已经捕获的结果。 You could consider a cached generator instead of a true generator. 您可以考虑使用缓存的生成器而不是真正的生成器。 You can shared the cached generator around as well, and if any client walks to an item you haven't been to yet, it will advance. 您也可以共享缓存的生成器,如果有任何客户端走到您尚未到达的项目,它将会前进。 This is similar to the tee() method, but does the tee functionality in the generator/cache itself instead of requiring the client to do it. 这与tee()方法类似,但是在生成器/缓存本身中执行tee功能而不是要求客户端执行此操作。

  • Generator has side effects, but no history, and you want to be able to restart anywhere. Generator有副作用,但没有历史记录,您希望能够在任何地方重新启动。 Consider writing it as a coroutine , where you can pass in the value to start at any time. 考虑将其写为协程 ,您可以随时传入值。

  • Generator has side effects AND history, meaning that the state of the generator at G(x) depends on the results of G(x-1), and so you can't just pass x back into it to start anywhere. 生成器具有副作用和历史,这意味着G(x)处的生成器状态取决于G(x-1)的结果,因此您不能将x传回其中以从任何地方开始。 In this case, I think you'd need to be more specific about what you are trying to do, as the result depends not just on the generator, but on the state of other data. 在这种情况下,我认为您需要更具体地了解您要执行的操作,因为结果不仅取决于生成器,还取决于其他数据的状态。 Probably, in this case, there is a better way to do it. 在这种情况下,可能有更好的方法。

The comment for itertools.tee was my first guess as well. itertools.tee的评论也是我的第一个猜测。 Because of the warning that you shouldn't advance the original generator any longer after using tee, I might write something like this to spin off a copy: 由于警告你不应该在使用T恤后再推进原始发电机,我可能会写这样的东西来分拆副本:

>>> from itertools import tee
>>>
>>> def foo():
...   i = 0
...   while i < 10:
...     i += 1
...     yield i
...
>>>
>>> it = foo()
>>> it.next()
1
>>> it, other = tee(it)
>>> it.next()
2
>>> other.next()
2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM