首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >自动展开的动态列表

自动展开的动态列表
EN

Stack Overflow用户
提问于 2012-06-29 16:08:58
回答 4查看 3.9K关注 0票数 6

如何使Python等效于来自Pop-11的pdtolist

假设我有一个名为g的生成器,它一次只返回一个整数。我想要构造一个列表,它是一个,当我请求在列表的当前末尾之外的值时,它会自动增长。例如:

代码语言:javascript
复制
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

术语--预测一个可能的误解:一个列表是一个“动态数组”,但这不是我的意思;我想要一个更抽象的“动态列表”。

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

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-07-13 16:11:09

非常感谢所有提出想法的人!以下是我从所有回应中收集到的信息。这保留了普通list类中的大多数功能,在必要时添加了额外的行为以满足额外的需求。

代码语言:javascript
复制
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)))

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

有些尴尬依然存在。像a = a[0:4]这样的赋值成功地截断了历史记录,但是结果列表不再自动扩展.相反,使用del a[0:4]保留自动增长属性。此外,我也不完全满意必须识别一个神奇的值,2147483647,代表最近的项目。

票数 2
EN

Stack Overflow用户

发布于 2012-06-29 16:22:39

这可能会让你开始:

代码语言:javascript
复制
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)

您将需要为片添加一些特殊处理(目前,它们只是返回一个正常列表,这样就失去了动态行为)。另外,如果您希望生成器本身成为一个列表项,这会增加一些复杂性。

票数 2
EN

Stack Overflow用户

发布于 2012-06-29 16:29:10

刚刚回答了另一个类似的问题,并决定更新我对你的回答,这是如何?

代码语言:javascript
复制
class dynamic_list(list):
    def __init__(self,num_gen):
        self._num_gen = num_gen
    def __getitem__(self,index):
        if isinstance(index, int):
            self.expandfor(index)
            return super(dynamic_list,self).__getitem__(index)

        elif isinstance(index, slice):
            if index.stop<index.start:
                return super(dynamic_list,self).__getitem__(index)
            else:
                self.expandfor(index.stop if abs(index.stop)>abs(index.start) else index.start)
            return super(dynamic_list,self).__getitem__(index)

    def __setitem__(self,index,value):
        if isinstance(index, int):
            self.expandfor(index)
            return super(dynamic_list,self).__setitem__(index,value)

        elif isinstance(index, slice):
            if index.stop<index.start:
                return super(dynamic_list,self).__setitem__(index,value)
            else:
                self.expandfor(index.stop if abs(index.stop)>abs(index.start) else index.start)
            return super(dynamic_list,self).__setitem__(index,value)

    def expandfor(self,index):
            rng = []
            if abs(index)>len(self)-1:
                if index<0:
                    rng = xrange(abs(index)-len(self))
                else:
                    rng = xrange(abs(index)-len(self)+1)
            for i in rng:
                self.append(self._num_gen.next())
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11265282

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档