An implementation of a variation on "for 1 <= i <= 10" [was Re: PEP 276 Simple Iterator for ints (fwd)]
Nick Mathewson
QnickQm at alum.mit.edu
Thu Dec 6 20:00:16 EST 2001
A while ago, Greg (I believe) proposed an alternative to PEP-276 that
would allow iteration syntax of the form "for 1 <= i <= 10".
In article <eppstein-2691AC.13312906122001 at news.service.uci.edu>,
David Eppstein wrote:
[...]
> But anyway, it would also be acceptable to me to use a syntax like
> "for i in lb < ... <= ub". This would also answer the other common
> objection that all for-loops must use "for var in iterator" syntax.
> I prefer the other syntax, because I think this one is verbose in a way
> that doesn't actually improve readability (verbosity that improves
> readability is better than conciseness, though).
Here's some code that implements almost this behavior. Now you can type:
for i in 1 <= ints <= 10:
print i
I don't have "for i in ints <= 10" going yet, but that should be a fairly
easy extension.
This code requires that you have at least Python 2.2 for the iterator
logic to work. Python2.2 is still in beta, but hey -- so is this
code. :)
============================================================
#!/usr/bin/python
class Integers:
def __init__(self, step=None, auto=0):
self.lb = None #Lower bound (inclusive)
self.ub = None #Upper bound (inclusive)
self.up = None #Flag: Are we counting up (a<i<c) or down (a>i>c)?
self.step = step #Stepping increment
self.auto = auto #Automatically return an iterator when we have 2
# bounds?
def __gt__(self, n):
self.lb = n+1
if self.ub == None: self.up = 1
if self.auto and self.ub != None and self.lb != None:
return iter(self)
else:
return self
def __lt__(self, n):
self.ub = n-1
if self.lb == None: self.up = 0
if self.auto and self.ub != None and self.lb != None:
return iter(self)
else:
return self
def __ge__(self, n):
self.lb=n
if self.ub == None: self.up = 1
if self.auto and self.ub != None and self.lb != None:
return iter(self)
else:
return self
def __le__(self, n):
self.ub=n
if self.lb == None: self.up = 0
if self.auto and self.ub != None and self.lb != None:
return iter(self)
else:
return self
def __nonzero__(self):
return 1
def __iter__(self):
if self.step == None:
self.step = (-1, 1)[self.up]
else:
assert self.step != 0 and self.up == (self.step > 0)
if self.up:
return iter(xrange(self.lb, self.ub+1, self.step))
else:
return iter(xrange(self.ub, self.lb-1, self.step))
ints = Integers(step=1, auto=1)
if __name__=='__main__':
assert [i for i in 1 <= Integers() <= 10] == range(1,11)
assert [i for i in 10 >= Integers() >= 1] == range(10,0,-1)
assert [i for i in 1 < Integers() < 10] == range(2,10)
assert [i for i in 10 > Integers() > 1] == range(9,1,-1)
assert [i for i in 1 < Integers() <= 10] == range(2,11)
assert [i for i in 10 > Integers() >= 1] == range(9,0,-1)
assert [i for i in 1 <= Integers() < 10] == range(1,10)
assert [i for i in 10 >= Integers() > 1] == range(10,1,-1)
assert [i for i in 2 <= Integers(step=2) < 99] == range(2,99,2)
n = 0
for i in 1 <= ints <= 10:
for j in 1 <= ints <= 10:
n += 1
assert n == 100
assert zip(1 <= ints <= 3, 1 <= ints <= 3) == zip((1,2,3), (1,2,3))
============================================================
What-a-tangled-web-we-weave-when-iterators-interleave'ly yours,
--
Nick Mathewson <Q nick Q m at alum dot mit dot edu>
Remove Q's to respond. No spam.
More information about the Python-list
mailing list