jfs*_*jfs 16 python range biginteger xrange python-3.x
xrange 函数不适用于大整数:
>>> N = 10**100
>>> xrange(N)
Traceback (most recent call last):
...
OverflowError: long int too large to convert to int
>>> xrange(N, N+10)
Traceback (most recent call last):
...
OverflowError: long int too large to convert to int
Run Code Online (Sandbox Code Playgroud)
Python 3.x:
>>> N = 10**100
>>> r = range(N)
>>> r = range(N, N+10)
>>> len(r)
10
Run Code Online (Sandbox Code Playgroud)
range()Python 2.x 有py3k内置函数的后端吗?
我正在寻找一个完整的"懒惰"实现range(),而不只是部分实现它的一些功能.
Ale*_*lli 19
我相信没有backport(毕竟Py 3完全消除了int/long的区别,但是在2.*它在这里留下来;-)但是不难破解你自己的,例如......:
import operator
def wowrange(start, stop, step=1):
if step == 0:
raise ValueError('step must be != 0')
elif step < 0:
proceed = operator.gt
else:
proceed = operator.lt
while proceed(start, stop):
yield start
start += step
Run Code Online (Sandbox Code Playgroud)
编辑出现(在PY 3 x范围的正常宗旨,范围)OP不只是要循环,而且也len和in运营商(后者则上述发电机的工作,但慢慢地-优化是可能的).对于这样的丰富性,一个班级更好......:
import operator
class wowrange(object):
def __init__(self, start, stop=None, step=1):
if step == 0: raise ValueError('step must be != 0')
if stop is None: start, stop = 0, start
if step < 0:
self.proceed = operator.gt
self.l = (stop-start+step+1)//step
else:
self.proceed = operator.lt
self.l = (stop-start+step-1)//step
self.lo = min(start, stop)
self.start, self.stop, self.step = start, stop, step
def __iter__(self):
start = self.start
while self.proceed(start, self.stop):
yield start
start += self.step
def __len__(self):
return self.l
def __contains__(self, x):
if x == self.stop:
return False
if self.proceed(x, self.start):
return False
if self.proceed(self.stop, x):
return False
return (x-self.lo) % self.step == 0
Run Code Online (Sandbox Code Playgroud)
如果这里有潜伏或类似的故障,我不会感到惊讶,但是,我希望这会有所帮助!
再次编辑:我看到索引也是必需的.编写自己的文章太难了__getitem__吗?我想是的,所以在这里它也是,在银盘上供应......:
def __getitem__(self, i):
if i < 0:
i += self.l
if i < 0: raise IndexError
elif if i >= self.l:
raise IndexError
return self.start + i * self.step
Run Code Online (Sandbox Code Playgroud)
我不知道3.0是否range支持切片(xrange在最近的2.*版本中没有 - 它曾经使用过,但由于复杂性是荒谬的并且容易出现错误而被删除),但我想我必须在沙子中绘制一条线在某个地方,所以我不打算添加它;-).
Ant*_*wns 11
好的,这是一个更全面的重新实现.
class MyXRange(object):
def __init__(self, a1, a2=None, step=1):
if step == 0:
raise ValueError("arg 3 must not be 0")
if a2 is None:
a1, a2 = 0, a1
if (a2 - a1) % step != 0:
a2 += step - (a2 - a1) % step
if cmp(a1, a2) != cmp(0, step):
a2 = a1
self.start, self.stop, self.step = a1, a2, step
def __iter__(self):
n = self.start
while cmp(n, self.stop) == cmp(0, self.step):
yield n
n += self.step
def __repr__(self):
return "MyXRange(%d,%d,%d)" % (self.start, self.stop, self.step)
# NB: len(self) will convert this to an int, and may fail
def __len__(self):
return (self.stop - self.start)//(self.step)
def __getitem__(self, key):
if key < 0:
key = self.__len__() + key
if key < 0:
raise IndexError("list index out of range")
return self[key]
n = self.start + self.step*key
if cmp(n, self.stop) != cmp(0, self.step):
raise IndexError("list index out of range")
return n
def __reversed__(self):
return MyXRange(self.stop-self.step, self.start-self.step, -self.step)
def __contains__(self, val):
if val == self.start: return cmp(0, self.step) == cmp(self.start, self.stop)
if cmp(self.start, val) != cmp(0, self.step): return False
if cmp(val, self.stop) != cmp(0, self.step): return False
return (val - self.start) % self.step == 0
Run Code Online (Sandbox Code Playgroud)
还有一些测试:
def testMyXRange(testsize=10):
def normexcept(f,args):
try:
r = [f(args)]
except Exception, e:
r = type(e)
return r
for i in range(-testsize,testsize+1):
for j in range(-testsize,testsize+1):
print i, j
for k in range(-9, 10, 2):
r, mr = range(i,j,k), MyXRange(i,j,k)
if r != list(mr):
print "iter fail: %d, %d, %d" % (i,j,k)
if list(reversed(r)) != list(reversed(mr)):
print "reversed fail: %d, %d, %d" % (i,j,k)
if len(r) != len(mr):
print "len fail: %d, %d, %d" % (i,j,k)
z = [m for m in range(-testsize*2,testsize*2+1)
if (m in r) != (m in mr)]
if z != []:
print "contains fail: %d, %d, %d, %s" % (i,j,k,(z+["..."])[:10])
z = [m for m in range(-testsize*2, testsize*2+1)
if normexcept(r.__getitem__, m) != normexcept(mr.__getitem__, m)]
if z != []:
print "getitem fail: %d, %d, %d, %s" % (i,j,k,(z+["..."])[:10])
Run Code Online (Sandbox Code Playgroud)
来自文档:
注意
xrange()旨在简单快速.实现可能会对此实施限制.Python的C实现将所有参数限制为本机C long("短"Python整数),并且还要求元素的数量适合本机C long.如果需要更大的范围,可以使用itertools模块制作备用版本:islice(count(start,step),(stop-start + step-1)// step).
或者使用生成器重新实现xrange:
def myxrange(a1, a2=None, step=1):
if a2 is None:
start, last = 0, a1
else:
start, last = a1, a2
while cmp(start, last) == cmp(0, step):
yield start
start += step
Run Code Online (Sandbox Code Playgroud)
和
N = 10**100
len(list(myxrange(N, N+10)))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
13026 次 |
| 最近记录: |