Python 3 中 range() 如何分配内存?

问题描述 投票:0回答:2

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

那么,考虑到这一点,有人可以解释一下 Python 中的

range()
如何使用内存吗?

我知道Python 2中的

range()
会创建一个值列表,所以这很容易理解,但是在Python 3中,我不断看到人们说它“创建一个新对象”或创建一个“迭代器对象”,但是什么计算机在内存方面有内部行为吗?

另外,据我了解,for 循环的工作方式与 Java 中 for-each 循环的工作方式相同,那么,如果像

for n in range(6)
这样的函数不迭代 0-5 的 6 个数字的列表,它如何工作?

需要明确的是,我知道,作为初学者,内存使用不应该成为问题,但我只是想知道事情在幕后是如何工作的。

python c memory-management range
2个回答
1
投票

Python 3

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

它按需“生成”数字,在这种情况下,“需求”就是循环

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

注意:这不是

range
的真正实现;真正的比这复杂得多。

上面的函数不分配任何内存,但可以像

range()
一样使用。

for n in range_func(6):
    print(n)

0
投票

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

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

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

您还说:“我只是喜欢知道事物在幕后是如何工作的” - 使用高阶语言的全部意义通常是您不需要确切地知道幕后发生了什么。知道

range()
是一种非常有效的访问一系列值的方法就足够了,同时具有较小的内存占用和良好的性能,绝对与创建列表或用 Python 编写生成器等替代方案相比做同样的事情。

“像 for n in range(6): 这样的函数是如何实现的?”——这不是一个 function,但它可以工作,因为范围可迭代,并且

for
可以从头到尾迭代其内容。您可以将
range(6)
替换为任何可迭代对象,并且
for
的工作方式完全相同(除了
n
当然会采用可迭代对象中的相关值。

© www.soinside.com 2019 - 2024. All rights reserved.