生成无限列表?

时间:2018-08-15 12:32:16

标签: python python-3.x list infinite

知道这很可能以失败告终,我想知道Python将如何处理这种情况,以及我的代码是否实际上“有意义”,至少在原则上是这样。 所以这是我的尝试,我是python的新手(几天前),所以我确信我的代码对于有更多经验的人来说似乎很有趣,但是请耐心等待。

def make_inf_lst(lst):
  lst = [0]
  while 1 == 1:
    for i in range(0, len(lst)):
      add = lst[i] + 1
      lst.append(add)
print(make_inf_lst([]))

这是我在DOS窗口中尝试运行上面的错误:

Traceback (most recent call last):
  File "break_python.py", line 7, in <module>
    print(make_inf_lst([]))
  File "break_python.py", line 6, in make_inf_lst
    lst.append(add)
MemoryError

谢谢。

5 个答案:

答案 0 :(得分:6)

具有“无限”数据结构的语言实际上正在生成对象,这些对象会延迟或“按需”生成其值。他们创建一个对象,而不是先创建整个列表,当要求输入值时,可以在那个时候创建​​它。

在Python中,最容易使用生成器进行管理。

def make_inf_sequence():
    x = 0
    while True:
        yield x
        x = x + 1

# This returns immediately
naturals = make_inf_sequence()

# This loop runs forever
for i in naturals:
    print(i)

答案 1 :(得分:2)

基本上有两件事可以阻止无限列表的打印(这似乎是代码的最终目标):

  1. 计算机将耗尽内存。
  2. 列表的创建将花费无限时间,这意味着它将永远不会完成,并且实际打印也不会开始。

如果您想象一台虚拟的计算机,它具有无限的内存和无限的计算速度,则可以打印列表。

但是,某些语言通过“惰性”来支持无限列表,这意味着它们将只计算在特定点上所需列表的一部分。然后您可以定义一个无限列表并要求其打印出例如其中的前100个值。

有关延迟计算的更多信息: https://en.m.wikipedia.org/wiki/Lazy_evaluation

答案 2 :(得分:1)

从立即获得访问宇宙中所有成员的意义上讲,它不能是无限的。那将是不可能的-无限长度意味着需要无限的内存。从错误中您可以看到,您没有无限的内存。如其他人所述,您可以用速度来换长度:

select sum(cnt)
from (select value1, count(*) as cnt
      from a
      group by value1
      having sum(value2 = 0) > 0
     ) a;

如果需要的话,在这里我将常规列表与动态扩展结合在一起。我不必从一个空列表开始,如果我愿意的话,我可以预先制作出前N个元素。

您当然可以重载运算符(+,-等等)。关键是一切都是一口气完成的。通过这种方式,您甚至可以添加和减去无限列表。

您甚至可以使用内存管理来改进此功能,并且如果一段时间内没有查看,则可以删除列表的开头,但是我认为这超出了范围。更具功能性的方法是保留当前数字和继续方式(我添加了from copy import deepcopy class infinite_ints: def __init__(self): self.list = [] self.trans = lambda x: x; def __getitem__(self,at): try: return self.trans(self.list[at]) except IndexError: self.list += [i for i in range(len(self.list),at+1)] return self.trans(self.list[at]) def apply(self,function): new_list = deepcopy(self) new_list.trans = lambda x,f=function,p=self.trans: f(p(x)) return new_list >>> x[2] 2 >>> x[12] 12 >>> x[43] 43 >>> y = x.apply(lambda x: x+1) >>> y[59] 60 类似于内置的prev

__next__

同样,可以很容易地实现运算符(而不仅仅是表示形式)或跳转多个。

答案 3 :(得分:1)

构建列表时,您的计算机有时会耗尽内存,这就是导致您看到错误的原因。不可能有无限列表,因为内存是有限的资源。

或者,您可以使用无限迭代器。标准库提供了一些无限迭代器。根据您的示例,我认为最适合您的情况的是itertools.count

样品用量:

>>> from itertools import count
>>> it = count()
>>> next(it)
0
>>> next(it)
1

您还可以指定自定义起点:

>>> from itertools import count
>>> it = count(5)
>>> next(it)
5
>>> next(it)
6

还有一个自定义步骤:

>>> from itertools import count
>>> it = count(5, 2)
>>> next(it)
5
>>> next(it)
7
>>> next(it)
9

答案 4 :(得分:0)

无限数据结构确实很有意义,但是必须总是进行延迟评估。这意味着您的数据结构不能立即构建其所有元素,然后再四处移动(就像我们通常使用适合内存的list一样)。相反,您的数据结构需要根据需要提供值。

在Python中,不能有无限的list,因为list渴望而不是懒惰(就像Python中的大多数事情一样,渴望是默认的)。清楚一点,我在这里谈论的是list类型。 Python术语,而不是某些序列的抽象概念(某些人可能称其为列表)。

您可以通过使用名为generator的方法来进行延迟评估。如果要生成序列1,2,3,4,...,则可以使用以下代码进行生成:

def gen_natural_numbers():
    cur = 1
    while True:
        yield cur
        cur += 1

natural_num_gen = gen_natural_numbers()
print("One: ", next(natural_num_gen))
print("Two: ", next(natural_num_gen))
print("Three: ", next(natural_num_gen))

此输出:

One:  1
Two:  2
Three:  3

很显然,您不必在3处停止。您不必在任何地方停止(除非您创建的int实际上不适合内存)。如果您继续调用next,则生成器将继续向您返回值。

在进行过程中,垃圾收集器可以从不再包含引用的内存中删除值。这完全是另一个主题,但是应该注意的是,只要您不永远保留引用,那么使用生成器时,程序也不会耗尽内存。