代码之家  ›  专栏  ›  技术社区  ›  TheRealNoofle

在Python 3中,range()是如何分配内存的?

  •  1
  • TheRealNoofle  · 技术社区  · 2 年前

    我是一名初级程序员,我上了C语言的课,对不同的函数和数据类型如何以不同的方式分配内存有了很好的理解(我相信并希望成为)。

    所以,考虑到这一点,有人能解释一下 range() 在Python中使用内存,好吗?

    我知道 范围() 在Python 2中会创建一个值列表,所以这很容易理解,但在Python 3中,我经常看到人们说它“创建一个新对象”或生成一个“迭代器对象”,但计算机内部对内存做什么?

    此外,据我所知,对于循环,每个循环在Java中的工作方式都是一样的,那么函数 for n in range(6) 如果它不迭代0-5的6个数字的列表,是否有效?

    需要明确的是,我知道,作为一个初学者,记忆使用不应该是一个问题,但我只是喜欢知道事情是如何在引擎盖下工作的。

    2 回复  |  直到 2 年前
        1
  •  1
  •   dolmok    2 年前

    Python 3 range() 对象不会通过创建来分配内存;它是一个 sequence object 。它所包含的只是开始值、停止值和步长值。

    它根据需要“生成”数字,在这种情况下,“需求”就是循环 for n in range(6): 。在对象上“迭代”时,每次迭代都会计算下一个整数。

    这个 range 对象在调用时返回迭代器 __iter__() 这个 for 循环会自动调用此函数。

    我们可以通过调用获得下一个值 next() 例如:

    r = range(6)
    i = r.__iter__()
    
    print(next(i))  # 0
    print(next(i))  # 1
    print(next(i))  # 2
    print(next(i))  # 3
    print(next(i))  # 4
    print(next(i))  # 5
    print(next(i))  # raises 'StopIteration'
    

    next() 加薪 StopIteration .

    一种可能的实施方式是:

    def range_func(stop):
        i = 0
        while i < stop:
            yield i
            i += 1
    

    注意:这不是的真正实现 范围 ;真正的比这复杂得多。

    上面的函数不分配任何内存,但可以像这样使用 范围() .

    for n in range_func(6):
        print(n)
    
        2
  •  0
  •   Grismar    2 年前

    你说:“我知道Python 2中的range()会创建一个值列表”-我不认为这完全是真的,但这并不重要,因为在这个阶段你可能不应该使用Python 2。然而,重要的是要意识到,Python有许多不同的实现,它们不需要“在后台”做同样的事情,只需要是语言的正确实现。

    文档中解释了它如何适用于CPython等常见实现: https://docs.python.org/3/library/stdtypes.html#typesseq-range

    具体来说:“范围类型相对于常规列表或元组的优势在于,范围对象总是占用相同(少量)的内存,无论它所代表的范围大小(因为它只存储开始、停止和步长值,根据需要计算单个项和子范围)。”

    你还说:“我只是喜欢知道引擎盖下的事情是如何运作的”——使用更高阶语言的全部意义往往是,你不需要确切地知道引擎盖下面发生了什么。知道这一点就足够了 range() 是一种非常有效的方法,可以访问一系列值,同时具有较小的内存占用和良好的性能,与创建列表或用Python编写生成器等替代方法相比,这一点毋庸置疑。

    “对于范围(6)中的n,函数如何:”-这不是 作用 但它之所以有效,是因为范围可迭代且 for 因此可以从头到尾对其内容进行迭代。你可以替换 range(6) 具有任何可迭代的和 对于 工作原理完全相同(除了 n 当然会从iterable中假定相关值。