自动扩展的动态列表

Ste*_*ers 6 python pop-11

如何从Pop-11 制作Python等效的pdtolist

假设我有一个名为g的生成器,它一次返回一个整数.我想建立一个列表一个,因为我要求超出了列表的当前最终值可以自动增长.例如:

print a # => [ 0, 1, 2, g]
print a[0] # => 0
print a[1] # => 1
print a[2] # => 2
# (obvious enough up to here)

print a[6] # => 6
print a # => [ 0, 1, 2, 3, 4, 5, 6, g]
# list has automatically expanded

a = a[4:] # discard some previous values
print a # => [ 4, 5, 6, g]
print a[0] # => 4
Run Code Online (Sandbox Code Playgroud)

术语 - 预测可能的误解:列表是一个"动态阵列",但这不是我的意思; 我想要一个更抽象意义上的"动态列表".

为了更好地解释动机,假设您有999999999个要处理的项目.试图将所有这些同时放入内存(在正常列表中)将是一个挑战.生成器通过一次呈现一个问题来解决问题的这一部分; 每个按需创建或从磁盘单独读取.但是假设在处理过程中你想要引用一些最近的值,而不仅仅是当前的值?您可以记住单独列表中的最后一个(例如)十个值.但动态列表更好,因为它会自动记住它们.

Ste*_*ers 2

非常感谢所有贡献想法的人!以下是我从所有回复中收集到的内容。这保留了普通列表类的大部分功能,并在必要时添加附加行为以满足附加要求。

class DynamicList(list):
    def __init__(self, gen):
        self.gen = gen

    def __getitem__(self, index):
        while index >= len(self):
            self.append(next(self.gen))
        return super(DynamicList, self).__getitem__(index)

    def __getslice__(self, start, stop):
        # treat request for "last" item as "most recently fetched"
        if stop == 2147483647: stop = len(self)
        while stop >  len(self):
            self.append(next(self.gen))
        return super(DynamicList, self).__getslice__(start, stop)

    def __iter__(self):
        return self

    def next(self):
        n = next(self.gen)
        self.append(n)
        return n

a = DynamicList(iter(xrange(10)))
Run Code Online (Sandbox Code Playgroud)

以前生成的值可以作为项目或切片单独访问。如果请求的项目超出列表的当前末尾,则记录的历史记录将根据需要扩展。可以使用 一次性访问整个记录的历史记录,print a或使用 分配给普通列表b = a[:]。可以使用 删除记录的历史记录的一部分del a[0:4]。您可以使用 迭代整个列表for,随时删除或在合适的时候删除。如果到达生成值的末尾,StopIteration则会引发。

一些尴尬仍然存在。诸如成功截断历史记录之类的分配a = a[0:4],但结果列表不再自动扩展。而是用来del a[0:4]保留自动增长属性。另外,我对必须识别2147483647代表最新项目的神奇值 并不完全满意。