You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
126 lines
3.9 KiB
126 lines
3.9 KiB
#!/usr/bin/env python
|
|
|
|
"""
|
|
Copyright (c) 2006-2024 sqlmap developers (https://sqlmap.org/)
|
|
See the file 'LICENSE' for copying permission
|
|
"""
|
|
|
|
import numbers
|
|
|
|
class xrange(object):
|
|
"""
|
|
xrange的高级(重新)实现(支持切片/复制等操作)
|
|
参考: http://code.activestate.com/recipes/521885-a-pythonic-implementation-of-xrange/
|
|
|
|
>>> list(xrange(1, 9)) == list(range(1, 9))
|
|
True
|
|
>>> list(xrange(8, 0, -16)) == list(range(8, 0, -16))
|
|
True
|
|
>>> list(xrange(0, 8, 16)) == list(range(0, 8, 16))
|
|
True
|
|
>>> list(xrange(0, 4, 5)) == list(range(0, 4, 5))
|
|
True
|
|
>>> list(xrange(4, 0, 3)) == list(range(4, 0, 3))
|
|
True
|
|
>>> list(xrange(0, -3)) == list(range(0, -3))
|
|
True
|
|
>>> list(xrange(0, 7, 2)) == list(range(0, 7, 2))
|
|
True
|
|
>>> foobar = xrange(1, 10)
|
|
>>> 7 in foobar
|
|
True
|
|
>>> 11 in foobar
|
|
False
|
|
>>> foobar[0]
|
|
1
|
|
"""
|
|
|
|
# 使用__slots__来限制类的属性,只允许_slice属性,可以节省内存
|
|
__slots__ = ['_slice']
|
|
|
|
def __init__(self, *args):
|
|
# 如果第一个参数是xrange对象,则复制其属性
|
|
if args and isinstance(args[0], type(self)):
|
|
self._slice = slice(args[0].start, args[0].stop, args[0].step)
|
|
else:
|
|
# 否则创建新的slice对象
|
|
self._slice = slice(*args)
|
|
# 确保stop参数不为None
|
|
if self._slice.stop is None:
|
|
raise TypeError("xrange stop must not be None")
|
|
|
|
@property
|
|
def start(self):
|
|
# 返回起始值,如果未指定则默认为0
|
|
if self._slice.start is not None:
|
|
return self._slice.start
|
|
return 0
|
|
|
|
@property
|
|
def stop(self):
|
|
# 返回结束值
|
|
return self._slice.stop
|
|
|
|
@property
|
|
def step(self):
|
|
# 返回步长,如果未指定则默认为1
|
|
if self._slice.step is not None:
|
|
return self._slice.step
|
|
return 1
|
|
|
|
def __hash__(self):
|
|
# 返回slice对象的哈希值
|
|
return hash(self._slice)
|
|
|
|
def __repr__(self):
|
|
# 返回对象的字符串表示
|
|
return '%s(%r, %r, %r)' % (type(self).__name__, self.start, self.stop, self.step)
|
|
|
|
def __len__(self):
|
|
# 返回序列的长度
|
|
return self._len()
|
|
|
|
def _len(self):
|
|
# 计算序列的长度: (stop-1-start)//step + 1,确保结果不小于0
|
|
return max(0, 1 + int((self.stop - 1 - self.start) // self.step))
|
|
|
|
def __contains__(self, value):
|
|
# 判断value是否在序列中
|
|
# 条件1: value在start和stop范围内
|
|
# 条件2: value与start的差值能被step整除
|
|
return (self.start <= value < self.stop) and (value - self.start) % self.step == 0
|
|
|
|
def __getitem__(self, index):
|
|
# 支持通过索引或切片获取元素
|
|
if isinstance(index, slice):
|
|
# 如果是切片,返回新的xrange对象
|
|
start, stop, step = index.indices(self._len())
|
|
return xrange(self._index(start),
|
|
self._index(stop), step * self.step)
|
|
elif isinstance(index, numbers.Integral):
|
|
# 如果是整数索引
|
|
if index < 0:
|
|
# 处理负数索引
|
|
fixed_index = index + self._len()
|
|
else:
|
|
fixed_index = index
|
|
|
|
# 检查索引是否越界
|
|
if not 0 <= fixed_index < self._len():
|
|
raise IndexError("Index %d out of %r" % (index, self))
|
|
|
|
return self._index(fixed_index)
|
|
else:
|
|
raise TypeError("xrange indices must be slices or integers")
|
|
|
|
def _index(self, i):
|
|
# 计算第i个元素的实际值
|
|
return self.start + self.step * i
|
|
|
|
def index(self, i):
|
|
# 返回值为i的元素在序列中的索引位置
|
|
if self.start <= i < self.stop:
|
|
return i - self.start
|
|
else:
|
|
raise ValueError("%d is not in list" % i)
|