Skip to main content
Made class Squares PEP8 compatible
Source Link
Georg Plaz
  • 6k
  • 5
  • 44
  • 66

iterator is a more general concept: any object whose class has a __next__ method (next in Python 2) and an __iter__ method that does return self.

Every generator is an iterator, but not vice versa. A generator is built by calling a function that has one or more yield expressions (yield statements, in Python 2.5 and earlier), and is an object that meets the previous paragraph's definition of an iterator.

You may want to use a custom iterator, rather than a generator, when you need a class with somewhat complex state-maintaining behavior, or want to expose other methods besides __next__ (and __iter__ and __init__). Most often, a generator (sometimes, for sufficiently simple needs, a generator expression) is sufficient, and it's simpler to code because state maintenance (within reasonable limits) is basically "done for you" by the frame getting suspended and resumed.

For example, a generator such as:

def squares(start, stop): for i in range(start, stop): yield i * i generator = squares(a, b) 

or the equivalent generator expression (genexp)

generator = (i*i for i in range(a, b)) 

would take more code to build as a custom iterator:

class Squares(object): def __init__(self, start, stop): self.start = start self.stop = stop   def __iter__(self):  return self   def __next__(self): # next in Python 2 if self.start >= self.stop: raise StopIteration current = self.start * self.start self.start += 1 return current   iterator = Squares(a, b) 

But, of course, with class Squares you could easily offer extra methods, i.e.

def current(self): return self.start 

if you have any actual need for such extra functionality in your application.

iterator is a more general concept: any object whose class has a __next__ method (next in Python 2) and an __iter__ method that does return self.

Every generator is an iterator, but not vice versa. A generator is built by calling a function that has one or more yield expressions (yield statements, in Python 2.5 and earlier), and is an object that meets the previous paragraph's definition of an iterator.

You may want to use a custom iterator, rather than a generator, when you need a class with somewhat complex state-maintaining behavior, or want to expose other methods besides __next__ (and __iter__ and __init__). Most often, a generator (sometimes, for sufficiently simple needs, a generator expression) is sufficient, and it's simpler to code because state maintenance (within reasonable limits) is basically "done for you" by the frame getting suspended and resumed.

For example, a generator such as:

def squares(start, stop): for i in range(start, stop): yield i * i generator = squares(a, b) 

or the equivalent generator expression (genexp)

generator = (i*i for i in range(a, b)) 

would take more code to build as a custom iterator:

class Squares(object): def __init__(self, start, stop): self.start = start self.stop = stop def __iter__(self): return self def __next__(self): # next in Python 2 if self.start >= self.stop: raise StopIteration current = self.start * self.start self.start += 1 return current iterator = Squares(a, b) 

But, of course, with class Squares you could easily offer extra methods, i.e.

def current(self): return self.start 

if you have any actual need for such extra functionality in your application.

iterator is a more general concept: any object whose class has a __next__ method (next in Python 2) and an __iter__ method that does return self.

Every generator is an iterator, but not vice versa. A generator is built by calling a function that has one or more yield expressions (yield statements, in Python 2.5 and earlier), and is an object that meets the previous paragraph's definition of an iterator.

You may want to use a custom iterator, rather than a generator, when you need a class with somewhat complex state-maintaining behavior, or want to expose other methods besides __next__ (and __iter__ and __init__). Most often, a generator (sometimes, for sufficiently simple needs, a generator expression) is sufficient, and it's simpler to code because state maintenance (within reasonable limits) is basically "done for you" by the frame getting suspended and resumed.

For example, a generator such as:

def squares(start, stop): for i in range(start, stop): yield i * i generator = squares(a, b) 

or the equivalent generator expression (genexp)

generator = (i*i for i in range(a, b)) 

would take more code to build as a custom iterator:

class Squares(object): def __init__(self, start, stop): self.start = start self.stop = stop   def __iter__(self):  return self   def __next__(self): # next in Python 2 if self.start >= self.stop: raise StopIteration current = self.start * self.start self.start += 1 return current   iterator = Squares(a, b) 

But, of course, with class Squares you could easily offer extra methods, i.e.

def current(self): return self.start 

if you have any actual need for such extra functionality in your application.

deleted 7 characters in body
Source Link
Michael M.
  • 11.2k
  • 11
  • 22
  • 46

iterator is a more general concept: any object whose class has a __next__ method (next in Python 2) and an __iter__ method that does return self.

Every generator is an iterator, but not vice versa. A generator is built by calling a function that has one or more yield expressions (yield statements, in Python 2.5 and earlier), and is an object that meets the previous paragraph's definition of an iterator.

You may want to use a custom iterator, rather than a generator, when you need a class with somewhat complex state-maintaining behavior, or want to expose other methods besides __next__ (and __iter__ and __init__). Most often, a generator (sometimes, for sufficiently simple needs, a generator expression) is sufficient, and it's simpler to code because state maintenance (within reasonable limits) is basically "done for you" by the frame getting suspended and resumed.

For example, a generator such as:

def squares(start, stop): for i in range(start, stop): yield i * i generator = squares(a, b) 

or the equivalent generator expression (genexp)

generator = (i*i for i in range(a, b)) 

would take more code to build as a custom iterator:

class Squares(object): def __init__(self, start, stop): self.start = start self.stop = stop def __iter__(self): return self def __next__(self): # next in Python 2 if self.start >= self.stop: raise StopIteration current = self.start * self.start self.start += 1 return current iterator = Squares(a, b) 

But, of course, with class Squares you could easily offer extra methods, i.e.

 def current(self):   return self.start 

if you have any actual need for such extra functionality in your application.

iterator is a more general concept: any object whose class has a __next__ method (next in Python 2) and an __iter__ method that does return self.

Every generator is an iterator, but not vice versa. A generator is built by calling a function that has one or more yield expressions (yield statements, in Python 2.5 and earlier), and is an object that meets the previous paragraph's definition of an iterator.

You may want to use a custom iterator, rather than a generator, when you need a class with somewhat complex state-maintaining behavior, or want to expose other methods besides __next__ (and __iter__ and __init__). Most often, a generator (sometimes, for sufficiently simple needs, a generator expression) is sufficient, and it's simpler to code because state maintenance (within reasonable limits) is basically "done for you" by the frame getting suspended and resumed.

For example, a generator such as:

def squares(start, stop): for i in range(start, stop): yield i * i generator = squares(a, b) 

or the equivalent generator expression (genexp)

generator = (i*i for i in range(a, b)) 

would take more code to build as a custom iterator:

class Squares(object): def __init__(self, start, stop): self.start = start self.stop = stop def __iter__(self): return self def __next__(self): # next in Python 2 if self.start >= self.stop: raise StopIteration current = self.start * self.start self.start += 1 return current iterator = Squares(a, b) 

But, of course, with class Squares you could easily offer extra methods, i.e.

 def current(self):   return self.start 

if you have any actual need for such extra functionality in your application.

iterator is a more general concept: any object whose class has a __next__ method (next in Python 2) and an __iter__ method that does return self.

Every generator is an iterator, but not vice versa. A generator is built by calling a function that has one or more yield expressions (yield statements, in Python 2.5 and earlier), and is an object that meets the previous paragraph's definition of an iterator.

You may want to use a custom iterator, rather than a generator, when you need a class with somewhat complex state-maintaining behavior, or want to expose other methods besides __next__ (and __iter__ and __init__). Most often, a generator (sometimes, for sufficiently simple needs, a generator expression) is sufficient, and it's simpler to code because state maintenance (within reasonable limits) is basically "done for you" by the frame getting suspended and resumed.

For example, a generator such as:

def squares(start, stop): for i in range(start, stop): yield i * i generator = squares(a, b) 

or the equivalent generator expression (genexp)

generator = (i*i for i in range(a, b)) 

would take more code to build as a custom iterator:

class Squares(object): def __init__(self, start, stop): self.start = start self.stop = stop def __iter__(self): return self def __next__(self): # next in Python 2 if self.start >= self.stop: raise StopIteration current = self.start * self.start self.start += 1 return current iterator = Squares(a, b) 

But, of course, with class Squares you could easily offer extra methods, i.e.

def current(self): return self.start 

if you have any actual need for such extra functionality in your application.

2020 update: python 3 (__next__) as default
Source Link
Niko Fohr
  • 35.3k
  • 12
  • 113
  • 117

iterator is a more general concept: any object whose class has a next__next__ method (__next__next in Python 32) and an __iter__ method that does return self.

Every generator is an iterator, but not vice versa. A generator is built by calling a function that has one or more yield expressions (yield statements, in Python 2.5 and earlier), and is an object that meets the previous paragraph's definition of an iterator.

You may want to use a custom iterator, rather than a generator, when you need a class with somewhat complex state-maintaining behavior, or want to expose other methods besides next__next__ (and __iter__ and __init__). Most often, a generator (sometimes, for sufficiently simple needs, a generator expression) is sufficient, and it's simpler to code because state maintenance (within reasonable limits) is basically "done for you" by the frame getting suspended and resumed.

For example, a generator such as:

def squares(start, stop): for i in range(start, stop): yield i * i generator = squares(a, b) 

or the equivalent generator expression (genexp)

generator = (i*i for i in range(a, b)) 

would take more code to build as a custom iterator:

class Squares(object): def __init__(self, start, stop): self.start = start self.stop = stop def __iter__(self): return self def next__next__(self): # __next__next in Python 32 if self.start >= self.stop: raise StopIteration current = self.start * self.start self.start += 1 return current iterator = Squares(a, b) 

But, of course, with class Squares you could easily offer extra methods, i.e.

 def current(self): return self.start 

if you have any actual need for such extra functionality in your application.

iterator is a more general concept: any object whose class has a next method (__next__ in Python 3) and an __iter__ method that does return self.

Every generator is an iterator, but not vice versa. A generator is built by calling a function that has one or more yield expressions (yield statements, in Python 2.5 and earlier), and is an object that meets the previous paragraph's definition of an iterator.

You may want to use a custom iterator, rather than a generator, when you need a class with somewhat complex state-maintaining behavior, or want to expose other methods besides next (and __iter__ and __init__). Most often, a generator (sometimes, for sufficiently simple needs, a generator expression) is sufficient, and it's simpler to code because state maintenance (within reasonable limits) is basically "done for you" by the frame getting suspended and resumed.

For example, a generator such as:

def squares(start, stop): for i in range(start, stop): yield i * i generator = squares(a, b) 

or the equivalent generator expression (genexp)

generator = (i*i for i in range(a, b)) 

would take more code to build as a custom iterator:

class Squares(object): def __init__(self, start, stop): self.start = start self.stop = stop def __iter__(self): return self def next(self): # __next__ in Python 3 if self.start >= self.stop: raise StopIteration current = self.start * self.start self.start += 1 return current iterator = Squares(a, b) 

But, of course, with class Squares you could easily offer extra methods, i.e.

 def current(self): return self.start 

if you have any actual need for such extra functionality in your application.

iterator is a more general concept: any object whose class has a __next__ method (next in Python 2) and an __iter__ method that does return self.

Every generator is an iterator, but not vice versa. A generator is built by calling a function that has one or more yield expressions (yield statements, in Python 2.5 and earlier), and is an object that meets the previous paragraph's definition of an iterator.

You may want to use a custom iterator, rather than a generator, when you need a class with somewhat complex state-maintaining behavior, or want to expose other methods besides __next__ (and __iter__ and __init__). Most often, a generator (sometimes, for sufficiently simple needs, a generator expression) is sufficient, and it's simpler to code because state maintenance (within reasonable limits) is basically "done for you" by the frame getting suspended and resumed.

For example, a generator such as:

def squares(start, stop): for i in range(start, stop): yield i * i generator = squares(a, b) 

or the equivalent generator expression (genexp)

generator = (i*i for i in range(a, b)) 

would take more code to build as a custom iterator:

class Squares(object): def __init__(self, start, stop): self.start = start self.stop = stop def __iter__(self): return self def __next__(self): # next in Python 2 if self.start >= self.stop: raise StopIteration current = self.start * self.start self.start += 1 return current iterator = Squares(a, b) 

But, of course, with class Squares you could easily offer extra methods, i.e.

 def current(self): return self.start 

if you have any actual need for such extra functionality in your application.

Added in Python 3 coment in the code directly
Source Link
Loading
Maybe `xrange()` should be `range()` (remember to delete the last line)
Source Link
Fabiano
  • 5.2k
  • 8
  • 44
  • 70
Loading
Maybe `xrange()` should be `range()` (remember to delete the last line)
Source Link
Loading
Emphasize the difference between a generator and a generator function (such as `squares`).
Source Link
Søren Løvborg
  • 8.8k
  • 2
  • 49
  • 43
Loading
just added current = self.start * self.start to return the squares.
Source Link
Loading
added 1346 characters in body
Source Link
Alex Martelli
  • 887.4k
  • 175
  • 1.3k
  • 1.4k
Loading
Source Link
Alex Martelli
  • 887.4k
  • 175
  • 1.3k
  • 1.4k
Loading