Method returning an Iterable Object

  • Thread starter Anjanesh Lekshminarayanan
  • Start date
A

Anjanesh Lekshminarayanan

Is there a way to return an iterable object ?

class twoTimes:
def __init__(self, n):
self.__n = n

def getNext():
self.__n *= 2
return self.__n


t = twoTimes(5)
while (n in t.getNext()): # while (n in t):
print (n)
 
A

Andreas Waldenburger

Is there a way to return an iterable object ?

class twoTimes:
def __init__(self, n):
self.__n = n

def getNext():
self.__n *= 2
return self.__n
Rename getNext() to next() and create another method named __iter__()
that just returns self. TwoTimes is now an iterator.

You can also replace the whole class with a function thusly:

def two_times(n):
for k in itertools.count(1):
yield n * (2**k)

This function is then called a generator (because it generates an
iterator). You can now say

infinitely_doubling_numbers = two_times(2)
for number in in infinitely_doubling_numbers:
print number

to the same effect as the iterator version above.

python.org seems uncooperative at the moment, but look up iterators or
the iterator protocol and generators if it works for you.

t = twoTimes(5)
while (n in t.getNext()): # while (n in t):
print (n)
You are aware that this is an infinite loop, as is my example above BTW?
(Probably just an example, but I ask just in case.)

Also, could it be that you mean "for n in t"?

regards
/W
 
A

Anjanesh Lekshminarayanan

You can also replace the whole class with a function thusly:
def two_times(n):
for k in itertools.count(1):
yield n * (2**k)

This function is then called a generator (because it generates an
iterator). You can now say

infinitely_doubling_numbers = two_times(2)
for number in in infinitely_doubling_numbers:
print number

Oh..this is new. Will checkup itertools. Thanks.
You are aware that this is an infinite loop, as is my example above BTW?
(Probably just an example, but I ask just in case.)

I was aware this was an infinite loop - just didnt want to put more
code for an example.
 
A

Andreas Waldenburger

Oh..this is new. Will checkup itertools. Thanks.
OK, happy I could help. But my point was the yield statement (in case
you didn't know about yield).

regards
/W
 
A

Anjanesh Lekshminarayanan

But how come a raise StopIteration in the next() method doesnt need to
be caught ? It works without breaking.

class twoTimes:
max = 10**10

def __init__(self, n):
self.__n = n

def next(self):
if self.__n > self.max:
raise StopIteration
self.__n *= 2
return self.__n

def __iter__(self):
return self


t = twoTimes(5)
c = 0

print (t.next())
print (t.next())

for n in t:
print n


Anjanesh
 
J

James Mills

But how come a raise StopIteration in the next() method doesnt need to
be caught ? It works without breaking.

Because this exception is specially dealt
with when iterating over an iterator. The
"raise StopIteration" is what causes the
iteration to stop.

Consider:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "foo.py", line 12, in next
raise StopIteration
StopIteration
x = EveryOther(xrange(10))
list(x) [0, 2, 4, 6, 8]

cheers
James
 
T

Terry Reedy

Anjanesh said:
But how come a raise StopIteration in the next() method doesnt need to
be caught ? It works without breaking.

The for-loop looks for and catches StopIteration. It is an essential
part of what defines a finite iterator.
(Note, in 3.0, next is renamed __next__ in conformance with all other
special methods. In 2.6, the rename is optional, I believe.)
class twoTimes:
max = 10**10

def __init__(self, n):
self.__n = n

There is no reason to mangle the attribute name.
Max should be a parameter, and self.max = max added to the init.
def next(self):
if self.__n > self.max:
raise StopIteration
self.__n *= 2
return self.__n

Are you sure you do not want to return once the initial value of n
passed to init?
def __iter__(self):
return self

Once you understand the above, you can rewrite it as a generator function:

def two_times(num, stop):
while num < stop:
yield num
num *=2

The two last lines can be switches if desired.
t = twoTimes(5)
c = 0

print (t.next())
print (t.next())

for n in t:
print n
[5, 10, 20, 40, 80, 160, 320, 640]

Terry Jan Reedy
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top