The Python 3 range()
object doesn't produce numbers immediately;
(Python 3 range()
对象不会立即产生数字。)
it is a smart sequence object that produces numbers on demand . (它是一个智能序列对象,可按需生成数字。)
All it contains is your start, stop and step values, then as you iterate over the object the next integer is calculated each iteration. (它所包含的只是您的开始,结束和步长值,然后在对对象进行迭代时,每次迭代都会计算出下一个整数。)
The object also implements the object.__contains__
hook , and calculates if your number is part of its range.
(该对象还实现object.__contains__
钩子 ,并计算您的数字是否属于其范围。)
Calculating is a O(1) constant time operation. (计算是O(1)恒定时间操作。)
There is never a need to scan through all possible integers in the range. (永远不需要扫描范围内的所有可能整数。)
From the range()
object documentation :
(从range()
对象文档中 :)
The advantage of the range
type over a regular list
or tuple
is that a range object will always take the same (small) amount of memory, no matter the size of the range it represents (as it only stores the start
, stop
and step
values, calculating individual items and subranges as needed).
(与常规list
或tuple
相比, range
类型的优势在于,范围对象将始终占用相同(少量)的内存,无论其表示的范围大小如何(因为它仅存储start
, stop
和step
值) ,根据需要计算单个项目和子范围)。)
So at a minimum, your range()
object would do:
(因此,至少,您的range()
对象可以:)
class my_range(object):
def __init__(self, start, stop=None, step=1):
if stop is None:
start, stop = 0, start
self.start, self.stop, self.step = start, stop, step
if step < 0:
lo, hi, step = stop, start, -step
else:
lo, hi = start, stop
self.length = 0 if lo > hi else ((hi - lo - 1) // step) + 1
def __iter__(self):
current = self.start
if self.step < 0:
while current > self.stop:
yield current
current += self.step
else:
while current < self.stop:
yield current
current += self.step
def __len__(self):
return self.length
def __getitem__(self, i):
if i < 0:
i += self.length
if 0 <= i < self.length:
return self.start + i * self.step
raise IndexError('Index out of range: {}'.format(i))
def __contains__(self, num):
if self.step < 0:
if not (self.stop < num <= self.start):
return False
else:
if not (self.start <= num < self.stop):
return False
return (num - self.start) % self.step == 0
This is still missing several things that a real range()
supports (such as the .index()
or .count()
methods, hashing, equality testing, or slicing), but should give you an idea.
(这仍然缺少真正的range()
支持的几件事(例如.index()
或.count()
方法,哈希,相等性测试或切片),但应该给您一个提示。)
I also simplified the __contains__
implementation to only focus on integer tests;
(我还简化了__contains__
实现,只专注于整数测试。)
if you give a real range()
object a non-integer value (including subclasses of int
), a slow scan is initiated to see if there is a match, just as if you use a containment test against a list of all the contained values. (如果为实的range()
对象提供非整数值(包括int
子类),则会启动慢速扫描以查看是否存在匹配项,就像您对包含的所有值的列表使用了包含测试。)
This was done to continue to support other numeric types that just happen to support equality testing with integers but are not expected to support integer arithmetic as well. (这样做是为了继续支持其他数字类型,这些数字类型恰好支持整数的相等性测试,但预计也不支持整数算术。)
See the original Python issue that implemented the containment test. (请参阅实现收容测试的原始Python问题 。)