Reuseable iterators - which is better?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • zefciu

    #1

    Reuseable iterators - which is better?

    In the tutorial there is an example iterator class that revesrses the
    string given to the constructor. The problem is that this class works
    only once, unlike built-in types like string. How to modify it that it
    could work several times? I have tried two approaches. They both work,
    but which of them is stylistically better?

    class Reverse: #original one
    "Iterator for looping over a sequence backwards"
    def __init__(self, data):
    self.data = data
    self.index = len(data)
    def __iter__(self):
    return self
    def next(self):
    if self.index == 0:
    raise StopIteration
    self.index = self.index - 1
    return self.data[self.index]

    class Reverse: #1st approach
    "Reuseable Iterator for looping over a sequence backwards"
    def __init__(self, data):
    self.data = data
    self.index = len(data)
    def __iter__(self):
    return self
    def next(self):
    if self.index == 0:
    self.index = len(self.data) #Reset when previous #
    iterator goes out
    raise StopIteration
    self.index = self.index - 1
    return self.data[self.index]

    class Reverse: #2nd approach
    "Reuseable Iterator for looping over a sequence backwards"
    def __init__(self, data):
    self.data = data
    def __iter__(self):
    self.index = len(self.data) #Reset as a part of iterator # creation
    return self
    def next(self):
    if self.index == 0:
    raise StopIteration
    self.index = self.index - 1
    return self.data[self.index]
  • Diez B. Roggisch

    #2
    Re: Reuseable iterators - which is better?

    zefciu schrieb:[color=blue]
    > In the tutorial there is an example iterator class that revesrses the
    > string given to the constructor. The problem is that this class works
    > only once, unlike built-in types like string. How to modify it that it
    > could work several times? I have tried two approaches. They both work,
    > but which of them is stylistically better?
    >
    > class Reverse: #original one
    > "Iterator for looping over a sequence backwards"
    > def __init__(self, data):
    > self.data = data
    > self.index = len(data)
    > def __iter__(self):
    > return self
    > def next(self):
    > if self.index == 0:
    > raise StopIteration
    > self.index = self.index - 1
    > return self.data[self.index]
    >
    > class Reverse: #1st approach
    > "Reuseable Iterator for looping over a sequence backwards"
    > def __init__(self, data):
    > self.data = data
    > self.index = len(data)
    > def __iter__(self):
    > return self
    > def next(self):
    > if self.index == 0:
    > self.index = len(self.data) #Reset when previous #
    > iterator goes out
    > raise StopIteration
    > self.index = self.index - 1
    > return self.data[self.index]
    >
    > class Reverse: #2nd approach
    > "Reuseable Iterator for looping over a sequence backwards"
    > def __init__(self, data):
    > self.data = data
    > def __iter__(self):
    > self.index = len(self.data) #Reset as a part of iterator # creation
    > return self
    > def next(self):
    > if self.index == 0:
    > raise StopIteration
    > self.index = self.index - 1
    > return self.data[self.index][/color]



    None. You don't reuse iterators! In the actualy example, reusage is
    possible due to the whole data being known & available. But there might
    be cases where this isn't possible - e.g. fetching data from a remote
    location which is too large to fit into memory for re-iteration.

    So generally speakiing, if you need an iterator, construct it.

    Regards,

    Diez

    Comment

    • Mitja Trampus

      #3
      Re: Reuseable iterators - which is better?

      zefciu wrote:[color=blue]
      > In the tutorial there is an example iterator class that revesrses the
      > string given to the constructor. The problem is that this class works
      > only once, unlike built-in types like string. How to modify it that it
      > could work several times? I have tried two approaches. They both work,
      > but which of them is stylistically better?[/color]

      Of the two posted below, I would much prefer the second one because iterators are not
      meant to be reused (so they can be used on streams and similar as well). Therefore,
      "resetting" an iterator by creating a new, similar one, is the natural way. Beware,
      however, that your code does not actually create a new iterator and breaks if you want to
      concurrently use more than one iterator of the same Reverse instance.
      The "normal" way would be to have
      def __iter__(self): return Reverse(self)
      as a method of the sequence that is meant to be iterated over in reverse. Plus, of course,
      everything but the __iter__ method from your second "reusable" iterator (which now isn't
      reusable any more).
      [color=blue]
      > class Reverse: #original one
      > "Iterator for looping over a sequence backwards"
      > def __init__(self, data):
      > self.data = data
      > self.index = len(data)
      > def __iter__(self):
      > return self
      > def next(self):
      > if self.index == 0:
      > raise StopIteration
      > self.index = self.index - 1
      > return self.data[self.index]
      >
      > class Reverse: #1st approach
      > "Reuseable Iterator for looping over a sequence backwards"
      > def __init__(self, data):
      > self.data = data
      > self.index = len(data)
      > def __iter__(self):
      > return self
      > def next(self):
      > if self.index == 0:
      > self.index = len(self.data) #Reset when previous #
      > iterator goes out
      > raise StopIteration
      > self.index = self.index - 1
      > return self.data[self.index]
      >
      > class Reverse: #2nd approach
      > "Reuseable Iterator for looping over a sequence backwards"
      > def __init__(self, data):
      > self.data = data
      > def __iter__(self):
      > self.index = len(self.data) #Reset as a part of iterator # creation
      > return self
      > def next(self):
      > if self.index == 0:
      > raise StopIteration
      > self.index = self.index - 1
      > return self.data[self.index][/color]

      Comment

      Working...