1 / 31

Computer Science 112

Computer Science 112. Fundamentals of Programming II Iterators. The for Loop. for value in <any collection>: <do something with value>. Allows the programmer to iterate through all of the values in a collection (or any other iterable object). The for Loop.

Download Presentation

Computer Science 112

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Computer Science 112 Fundamentals of Programming II Iterators

  2. The for Loop for value in <any collection>: <do something with value> Allows the programmer to iterate through all of the values in a collection (or any other iterable object)

  3. The for Loop for value in <any collection>: <do something with value> Users: list(<any collection>) # builds a list from the collection

  4. The for Loop for value in <any collection>: <do something with value> Users: list(<any collection>) # builds a list from the collection sum(<any collection of numbers>)

  5. The for Loop for value in <any collection>: <do something with value> Users: list(<any collection>) # builds a list from the collection sum(<any collection of numbers>) min(<any collection of comparables>)

  6. The for Loop for value in <any collection>: <do something with value> Users: list(<any collection>) # builds a list from the collection sum(<any collection of numbers>) min(<any collection of comparables>) map(<a function of one arg>, <any collection>)

  7. The for Loop for value in <any collection>: <do something with value> Users: list(<any collection>) # builds a list from the collection sum(<any collection of numbers>) min(<any collection of comparables>) map(<a function of one arg>, <any collection>) filter(<a predicate of one arg>, <any collection>)

  8. The for Loop for value in <any collection>: <do something with value> Users: list(<any collection>) # builds a list from the collection sum(<any collection of numbers>) min(<any collection of comparables>) map(<a function of one arg>, <any collection>) filter(<a predicate of one arg>, <any collection>) <a value> in <any collection>

  9. The Benefits of a for Loop class ArrayBag(object): DEFAULT_CAPACITY = 10 def __init__(self, sourceCollection = None): self._items = Array(ArrayBag.DEFAULT_CAPACITY) self._size = 0 if sourceCollection: for item in sourceCollection: self.add(item) Here we assume that sourceCollection is iterable bag = ArrayBag(range(1, 11))

  10. The Benefits of a for Loop class LinkedBag(object): def __init__(self, sourceCollection = None): self._items = None self._size = 0 if sourceCollection: for item in sourceCollection: self.add(item) Here we assume that sourceCollection is iterable bag = LinkedBag(range(1, 11))

  11. The Benefits of a for Loop class ArraySortedBag(object): def __init__(self, sourceCollection = None): self._items = Array(ArraySortedBag.DEFAULT_CAPACITY) self._size = 0 if sourceCollection: for item in sourceCollection: self.add(item) Here we assume that sourceCollection is iterable bag = ArraySortedBag([44, 33,55, 22, 10])

  12. The Benefits of a for Loop class ArrayBag(object): def__add__(self, other): """Returns a new bag containing the contents of self and other.""" result = ArrayBag(self) for item in other: result.add(item) return result Here we assume that self and other are iterable b3 = b1 + b2

  13. The Benefits of a for Loop class ArraySet(object): def__eq__(self, other): """Returns True if self equals other, or False otherwise.""" if self is other: return True iftype(self) != type(other) orlen(self) != len(other): return False for item in self: ifnot item in other: returnFalse return True Here we assume that self and other are iterable b1 == b2

  14. The Benefits of a for Loop class ArrayBag(object): def__str__(self): """Returns the string representation of self.""" return"{" + ", ".join(map(str, self)) + "}" Here we assume that self is iterable

  15. Loop Patterns and Iterators for i inrange(someInteger): <do something with i> for value in someCollection: <do something with value> When the PVM sees a for loop, it evaluates the second operand of in and then calls the iter function on its value The code in the iter function repeatedly fetches the next value in the second operand and binds it to the first operand After each fetch operation, the code in the loop body is run

  16. Two Loop Patterns for i inrange(someInteger): <do something with i> for value in someCollection: <do something with value> Thus, the second operand of in must include an __iter__ method in its class If you want your collection to be iterable, you must define an __iter__ method

  17. Implementing an Iterator class Array(object): def__init__(self, capacity, fillValue = None): self._items = list() for count inrange(capacity): self._items.append(fillValue) def__iter__(self): returniter(self._items) The __iter__ method of the Array class simply returns the result of calling iter on its underlying list

  18. ArrayBag Iterator: A Nice Try class ArrayBag(object): DEFAULT_CAPACITY = 10 def __init__(self, sourceCollection = None): self._items = Array(ArrayBag.DEFAULT_CAPACITY) self._size = 0 if sourceCollection: for item in sourceCollection: self.add(item) def __iter__(self): returniter(self._items) What’s wrong with this code?

  19. Designing an Iterator • The __iter__ method must initialize and maintain a cursor, which locates the current item • __iter__’s loop quits when the cursor goes off the end of the collection • The body of the loop yields the current item and advances the cursor

  20. Implementing an Iterator class ArrayBag(object): DEFAULT_CAPACITY = 10 def __init__(self, sourceCollection = None): self._items = Array(ArrayBag.DEFAULT_CAPACITY) self._size = 0 if sourceCollection: for item in sourceCollection: self.add(item) def __iter__(self): cursor = 0 while cursor < len(self): yield self._items[cursor] cursor += 1

  21. Running an Iterator def __iter__(self): cursor = 0 while cursor < len(self): yield self._items[cursor] cursor += 1 for item in bag: <do something with item> The app running the for loop runs in a different process from the iterator’s process collection D D D iterator

  22. Running an Iterator def __iter__(self): cursor = 0 while cursor < len(self): yield self._items[cursor] cursor += 1 for item in bag: <do something with item> The app running the for loop runs in a different process from the iterator’s process collection D D D iterator

  23. Running an Iterator def __iter__(self): cursor = 0 while cursor < len(self): yield self._items[cursor] cursor += 1 for item in bag: <do something with item> The app running the for loop runs in a different process from the iterator’s process collection D D D iterator

  24. Running an Iterator def __iter__(self): cursor = 0 while cursor < len(self): yield self._items[cursor] cursor += 1 for item in bag: <do something with item> The app running the for loop runs in a different process from the iterator’s process collection D D D iterator

  25. An Iterator for a Linked Structure • The cursor would be initialized to the head pointer (like a probe) • The loop quits when the cursor equals None • The value yielded is in the cursor’s node • The cursor is updated by setting it to the next node

  26. Implementing an Iterator class LinkedBag(object): def __init__(self, sourceCollection = None): self._items = None self._size = 0 if sourceCollection: for item in sourceCollection: self.add(item) def __iter__(self): cursor = self._items while cursor != None: yield cursor.data cursor = cursor.next

  27. Iterator Should Be Read-Only for item in bag: bag.remove(item) Mutations in the context of a for loop can cause the state of the underlying collection to become inconsistent with the state of the iterator

  28. Iterator Should Be Read-Only for item in bag: bag.remove(item) # Will raise an exception bag.clear() # Preferred method We can arrange for the collection to track mutations so that the iterator can detect illicit ones and raise exceptions

  29. Tracking Modifications class LinkedBag(object): def __init__(self, sourceCollection = None): self._items = None self._size = 0 self._modCount = 0 # Tracks mutations if sourceCollection: for item in sourceCollection: self.add(item) def add(self, item): self._items = Node(item, self._items) self._size += 1 self._modCount += 1 Each mutator method increments the mod count

  30. Detecting Modifications class LinkedBag(object): def __init__(self, sourceCollection = None): self._items = None self._size = 0 if sourceCollection: for item in sourceCollection: self.add(item) def __iter__(self): myModCount = self._modCount cursor = self._items while cursor != None: yield cursor.data if myModCount != self._modCount: # Gotcha! raiseAttributeError(\ "Cannot modify the backing store in a for loop") cursor = cursor.next

  31. For Monday Equality Start Chapter 6

More Related