#!/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)