给定一个发电机
g = ( <expr> for x in <iter> ),
有没有办法恢复用于定义g的表达式和迭代器?你知道吗
例如,函数的行为如下:
expr, iter = f( ( x*x for x in range(10) ) )
expr(2) # 4
expr(5) # 25
iter[1] # 1
iter[9] # 9
iter[10] # raises IndexError
我之所以列出自己的功能,就是因为这个。我希望它本质上像一个生成器,除了允许通过getitem访问,而不必在访问第k个元素之前遍历k-1元素。谢谢。你知道吗
编辑:下面是lazy list类的快照:
class LazyList(object):
def __init__(self, iter=None, expr=None):
if expr is None:
expr = lambda i: i
if iter is None:
iter = []
self._expr = expr
self._iter = iter
def __getitem__(self, key):
if hasattr(self._iter, '__getitem__'):
return self._expr(self._iter[key])
else:
return self._iter_getitem(key)
def __iter__(self):
for i in self._iter:
yield self._expr(i)
我省略了方法\u iter\u getitem。所有这些都是通过iter进行迭代,直到它到达key'th元素(或者如果key是片,则使用itertool的islice)。还有一些常见的llmap、llreduce等函数我省略了,但你可能猜得到它们是如何运行的。你知道吗
我希望能够分解生成器的动机之一是我可以像这样优雅地初始化这个类
l = LazyList(x*x for x in range(10))
而不是
l = LazyList(range(10), lambda x: x*x)
但真正的好处是,使用polish,这将是生成器概念的一个很好的概括,并且能够代替任何生成器(具有相同的内存节省优势)。你知道吗
我经常在Django中使用它,因为它可以很好地用于他们的查询集。我有很多依赖于列表结构的代码是惰性的,因为它返回多维数组,如果对其求值,将获取比我需要的更多的数据。你知道吗
我认为你的懒虫列表的概念是好的,但是你想直接访问生成器的n'th值的想法是有缺陷的。您使用
range(10)
作为迭代序列的例子是一个特例,其中所有值都是可以提前知道的。但是许多生成器是增量计算的,其中n值是基于n-1值计算的。斐波那契发生器就是这样一种:这给出了熟悉的系列1,1,2,3,5,8。。。其中第n项是第n-1项和第n-2项之和。所以没有办法直接跳到第10项,你必须通过第0-9项才能到达。你知道吗
也就是说,你的懒人列表很不错,有几个原因:
它允许您重新访问以前的值
它模拟直接访问,即使在覆盖下,生成器必须遍历所有增量值,直到到达“n”
它只计算实际需要的值,因为生成器是延迟计算的,而不是先发制人地计算1000个值,结果发现使用了前10个值
我能想到的最接近的方法是反汇编生成器表达式中的代码对象。像这样的
这给了我们一点暗示,但是还不太清楚。你知道吗
有another Stack Overflow question处理如何将Python字节码转换成可读的Python—也许您可以使用它来获得更具可读性的内容。你知道吗
相关问题 更多 >
编程相关推荐