在Python中不存储所有值的算术序列
我想表示一个均匀间隔的浮点数数组,也就是一个等差数列,起始值是a0,元素依次是a0、a0 + a1、a0 + 2a1、a0 + 3a1,等等。这个功能是numpy的arange()方法可以做到的,但它似乎会为整个数组分配内存,而我想用一个迭代器类来实现,这个类只存储a0、a1和n(元素的总数,可能会很大)。
在标准的Python包中,有没有现成的东西可以做到这一点?我找不到,所以我继续尝试:
class mylist():
def __init__(self, n, a0, a1):
self._n = n
self._a0 = a0
self._a1 = a1
def __getitem__(self, i):
if i < 0 or i >= self._n:
raise IndexError
return self._a0 + i * self._a1
def __iter__(self):
self._i = 0
return self
def next(self):
if self._i >= self._n:
raise StopIteration
value = self.__getitem__(self._i)
self._i += 1
return value
这样做合理吗,还是我在重复造轮子?
5 个回答
1
出于一些可能很明显的原因,当我遍历 mylist 时,使用
for i,x in enumerate(a): print i,a
并没有返回我期待的值,而是返回了一堆对 mylist 实例的引用。我哪里做错了?
问题出在 print i,a
这行代码上。你打印的是 a
,也就是一个数组。你应该打印 x
,而不是 a
。把这一行改成:
print i,x
还有几点建议:
- 把你的类名改成大写开头的格式,比如
class MyList
或者class Mylist
。 - 如果你在使用 Python 2.x,建议继承
object
。所以可以写成class MyList(object): ...
3
其他回答解决了眼前的问题。需要注意的是,如果你只想要一个迭代器,并且不需要随机访问,那么就没必要写一个完整的迭代器类。
def mylist(n, a0, a1):
for i in xrange(n):
yield a0 + i*a1
3
首先,你做错了一件事,应该是 for i, x in enumerate(a): print i, x
。
另外,我可能会建议你用生成器方法,这样就不用麻烦地处理 __iter__
和 next()
这些方法了。特别是因为你的解决方案不允许你同时用两个不同的迭代器遍历同一个 mylist
(因为 self._i
是类内部的局部变量)。
这个方法可能更好,它不仅可以让你随机访问,还能提供高效的迭代器。而且支持 in
和 len
操作符也是个额外的好处哦 :)
class mylist(object):
def __init__(self, n, a0, a1, eps=1e-8):
self._n = n
self._a0 = a0
self._a1 = a1
self._eps = eps
def __contains__(self, x):
y = float(x - self._a0) / self._a1
return 0 <= int(y) < self._n and abs(y - int(y)) < self._eps
def __getitem__(self, i):
if 0 <= i < self._n:
return self._a0 + i * self._a1
raise IndexError
def __iter__(self):
current = self._a0
for i in xrange(self._n):
yield current
current += self._a1
def __len__(self):
return self._n