Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Appendix O: Additional Python 2.2 Features Outline O.1 O.2 O.3 O.4 O.5 Introduction Iterators Generators Nested Scopes Internet and World Wide Web Resources 2002 Prentice Hall. All rights reserved. O.1 Introduction • Overview of new features in Python 2.2 (e.g., iterators, generators and nested scopes) that allow programmers to express algorithms more clearly and simply 2002 Prentice Hall. All rights reserved. O.2 Iterators • Special objects that define operations for progressing through sequences • Useful for many kinds of sequences, including list-like objects (such as built-in types list and tuple), program-defined container objects (e.g., trees) or unbounded sequences whose length is unknown (e.g., input and output streams) • __getitem__ intended for random attribute access (e.g., index access for lists or dictionary key lookups), rather than iteration • Can be more efficient for processing a sequence 2002 Prentice Hall. All rights reserved. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 # Fig. O.1: NewRange.py Class simulates range of # __getitem__ used in a for loop. Outline integer values class MyRange: """Simple class to simulate a range values""" Constructor receives valuesof forinteger parameters start, stop andNewRange.py step Constructor calls range to generate sequence def __init__( self, start, stop, step ): """Class MyRange constructor; takes start, stop and step""" of integers Provides subscript access (using operator []) self.__sequence = range( start, stop, step ) def __getitem__( self, subscript ): Python raises Returns element """Overridden sequence element access""" IndexError if subscript stored at specified subscriptlies out of bounds return self.__sequence[ subscript ] 2002 Prentice Hall. All rights reserved. Python 2.2b2 (#26, Nov 16 2001, 11:44:11) [MSC 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> >>> from NewRange import MyRange >>> myRange = MyRange( 0, 10, 1 ) >>> >>> print myRange[ 0 ] 0 >>> print myRange[ 8 ] 8 >>> >>> for value in myRange: ... print value, ... 0 1 2 3 4 5 6 7 8 9 Outline Fig. O.1 __getitem__ method to emulate iteration 2002 Prentice Hall. All rights reserved. Python 2.2b2 (#26, Nov 16 2001, 11:44:11) [MSC 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> >>> from NewRange import MyRange >>> myRange = MyRange( 0, 10, 1 ) >>> >>> currentIndex = 0 >>> >>> while 1: ... try: ... value = myRange[ currentIndex ] ... except IndexError: ... break ... else: ... print value, ... currentIndex += 1 ... 0 1 2 3 4 5 6 7 8 9 Outline Fig. O.2 __getitem__ and for loops 2002 Prentice Hall. All rights reserved. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 # Fig. O.3: NewRangeIterator.py # Iterator class that defines a sequence. class RangeIterator: """Simple class to simulate a range""" Outline NewRangeIterator .py def __init__( self, start, stop, step ): """RangeIterator constructor; takes start, stop and step""" self.__sequence = range( start, stop, step ) self.__nextValue = 0 # subscript of next value to produce def __iter__( self ): """Returns iterator for object of class RangeIterator""" return self def next( self ): """Iterator method to produce next value in sequence""" try: value = self.__sequence[ self.__nextValue ] except IndexError: raise StopIteration else: self.__nextValue += 1 return value def main(): Create object range1 that contains values 0-9 # create object of class RangeIterator, use for loop to iterate range1 = RangeIterator( 0, 10, 1 ) print "Iterate over the values in range1 using a for loop:" 2002 Prentice Hall. All rights reserved. 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 for value in range1: print value, Outline Uses for loop to iterate over object’s elements print NewRangeIterator Retrieve iterator forcall object by calling method iter .py class RangeIterator, next to iterate # create object of range2 = RangeIterator( 0, 10, 1 ) range2Iterator = iter( range2 ) # retrieve iterator for range2 print "\nCall method next for range2Iterator:" while 1: next for an object’s iterator progresses through values in an object’s sequence next raises StopIteration when there are no more values in the sequence try: value = range2Iterator.next() except StopIteration: break else: print value, print # create one object of class RangeIterator two iterators # for that object Objects can have more than one iterator range3 = RangeIterator( 0, 10, 1 ) range3Iterator1 = iter( range3 ) range3Iterator2 = iter( range3 ) print "\nCall next for two iterators of the same object:" 2002 Prentice Hall. All rights reserved. 66 67 68 69 70 71 72 73 74 for i in range( Using 10 ): more than one iterator on the same object can print "Loop iteration %d: range3Iterator1.next() = %d" % \ ( i, range3Iterator1.next() ) print "Loop iteration %d: range3Iterator2.next() = %d" % \ ( i, range3Iterator2.next() ) print lead to subtleOutline logic errors NewRangeIterator .py if __name__ == "__main__": main() 2002 Prentice Hall. All rights reserved. Iterate over the values in range1 using a for loop: 0 1 2 3 4 5 6 7 8 9 Outline Call method next for range2Iterator: 0 1 2 3 4 5 6 7 8 9 Call next for two iterators of the same object: Loop iteration 0: range3Iterator1.next() = 0 Loop iteration 0: range3Iterator2.next() = 1 Loop iteration 1: range3Iterator1.next() = 2 Loop iteration 1: range3Iterator2.next() = 3 Loop iteration 2: range3Iterator1.next() = 4 Loop iteration 2: range3Iterator2.next() = 5 Loop iteration 3: range3Iterator1.next() = 6 Loop iteration 3: range3Iterator2.next() = 7 Loop iteration 4: range3Iterator1.next() = 8 Loop iteration 4: range3Iterator2.next() = 9 Traceback (most recent call last): File "newrange3.py", line 74, in ? main() File "newrange3.py", line 67, in main print "Loop iteration %d: range3Iterator1.next() = %d" % \ File "newrange3.py", line 24, in next raise StopIteration StopIteration 2002 Prentice Hall. All rights reserved. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 # Fig. O.4: GuessingGame.py # Class and program to simulate computer guessing game. import random Outline GuessingGame.py class ComputerGuessingGame: """Class to guess a number randomly""" def __init__( self, value, lowerBound = 0, upperBound = 10 ): """ComputerGuesser constructor; takes secret number, lower and upper bounds""" self.realValue =Keeps valuevalue within upper and lower bounds # keep value within upper and lower bound if value < lowerBound: self.lower = value else: self.lower = lowerBound if value > upperBound: self.upper = value + 1 else: self.upper = upperBound def __iter__( self ): """Return iterator for object of class ComputerGuesser""" Produces return self a series of random guesses def next( self ): """Guesses a new value. If correct, raises StopIteration; otherwise returns guess""" guess = random.randrange( self.lower, self.upper ) 2002 Prentice Hall. All rights reserved. 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 If correct, raises StopIteration Outline if guess == self.realValue: raise StopIteration else: return guess GuessingGame.py def main(): # retrieve an integer from the user while 1: try: secretNumber = int( raw_input( "Enter number for computer to guess: " ) ) except ValueError: print "Please enter an integer." else: break print computerGuesser = ComputerGuessingGame( secretNumber ) numberOfWrongGuesses = iterator 0 Implicitly creates for ComputerGuessingGame object computerGuesser # print the incorrect guesses for wrongGuess in computerGuesser: numberOfWrongGuesses += 1 print "Computer guessed: %d" % wrongGuess print "\nGot secret number after %d wrong guesses." % \ numberOfWrongGuesses if __name__ == "__main__": main() 2002 Prentice Hall. All rights reserved. Enter number for computer to guess: 6 Computer Computer Computer Computer Computer Computer Computer Computer Computer guessed: guessed: guessed: guessed: guessed: guessed: guessed: guessed: guessed: Outline 1 7 1 1 3 9 9 1 8 Got secret number after 9 wrong guesses Enter number for computer to guess: 100 Computer Computer Computer Computer Computer Computer Computer Computer Computer Computer Computer Computer Computer guessed: guessed: guessed: guessed: guessed: guessed: guessed: guessed: guessed: guessed: guessed: guessed: guessed: 31 41 61 77 92 80 11 46 43 31 21 6 7 Got secret number after 13 wrong guesses. 2002 Prentice Hall. All rights reserved. O.3 Generators • Functions that return iterators • Resumable functions that are especially well suited for computing the values of a recursive sequence • Special kind of functions that can suspend computation, “remember” their local variables and later resume where the previous computation left off 2002 Prentice Hall. All rights reserved. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 # Fig. O.5: figO_05.py # Inefficient, recursive fibonacci calls. def fibonacci( n ): Outline figO_05.py if n < 0: raise ValueError, \ "Cannot computer fibonacci on negative number" elif n == 0 or n == 1: return n else: return fibonacci( n - 1 ) + fibonacci( n - 2 ) n = 0 value = 0 Compute smallest fibonacci( n ) > 1000 # compute smallest fibonacci( n ) > 1000 while value < 1000: value = fibonacci( n ) n += 1 print "The smallest fibonacci number greater than 1000 is:", value The smallest fibonacci number greater than 1000 is: 1597 2002 Prentice Hall. All rights reserved. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 Outline # Fig. O.6: figO_06.py # fibonacci generator. Import generators Define fibonacci generator from __future__ import generators figO_06.py Refers def fibonacci(): to next value in the sequence Return to value after the value indicated by nextItem nextItem = 0 # next value in the sequence beyondItem = 1 # value *after* the next value in the sequence Keyword yield suspends execution and returns intermediate value while 1: yield nextItem # return fibonacci( n ) # function resumes here when program calls next on # fibonacci's Functioniterator resumes here when program calls next on fibonacci’s iterator # compute the next fibonacci( n ) and fibonacci( n + 1 ) nextItem, beyondItem = beyondItem, nextItem + beyondItem Create iterator fibIterator = fibonacci() # create iterator for Fibonacci sequence result = 0 Find smallest Fibonacci number greater than 1000 # find smallest Fibonacci number greater than 1000 while result < 1000: result = fibIterator.next() print "The smallest fibonacci number greater than 1000 is:", result The smallest fibonacci number greater than 1000 is: 1597 2002 Prentice Hall. All rights reserved. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 # Fig O.7: figO_07.py # fibonacci generator for nth Fibonacci sequence element. Outline Generator raises a StopIteration exception when it returns from __future__ import generators figO_07.py def fibonacci( n ): nextItem = 0 # next value in the sequence beyondItem = 1 # value *after* the next value in the sequence currentN = 0 # n for which the generator is producing a value while currentN <= n: yield nextItem # return fibonacci( n ) # compute the next fibonacci( n ) and fibonacci( n + 1 ) nextItem, beyondItem = beyondItem, nextItem + beyondItem currentN += 1 while 1: # retrieve number from user try: fibNumber = int( raw_input( "Enter a number: " ) ) except ValueError: print "Please enter an integer." else: break print counter = 0 Python repeatedly callsimplicitly next to get valuefirst fortime result Iterator created fibonacci function is invoke # print fibonacci( n ) for all n <= fibNumber for result in fibonacci( fibNumber ): print "fibonacci( %d ) = %d" % ( counter, result ) counter += 1 2002 Prentice Hall. All rights reserved. Enter a number: 20 fibonacci( fibonacci( fibonacci( fibonacci( fibonacci( fibonacci( fibonacci( fibonacci( fibonacci( fibonacci( fibonacci( fibonacci( fibonacci( fibonacci( fibonacci( fibonacci( fibonacci( fibonacci( fibonacci( fibonacci( fibonacci( Outline 0 ) = 0 1 ) = 1 2 ) = 1 3 ) = 2 4 ) = 3 5 ) = 5 6 ) = 8 7 ) = 13 8 ) = 21 9 ) = 34 10 ) = 55 11 ) = 89 12 ) = 144 13 ) = 233 14 ) = 377 15 ) = 610 16 ) = 987 17 ) = 1597 18 ) = 2584 19 ) = 4181 20 ) = 6765 2002 Prentice Hall. All rights reserved. O.4 Nested Scopes • Address how identifier lookup takes place in nested functions • Most useful for programs that employ a functional-style of programming • Nested scoping enables an inner function to access variables that appear in the function’s outer scope 2002 Prentice Hall. All rights reserved. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 Outline # Fig. O.8: figO_08.py # Nested functions. def outer():Function inner prints message to indicate that function is executing figO_08.py def inner(): Calls built-in function dir to print list of print "\nFunction inner executing" print "The objects in inner's scope are:", dir() print "Function inner finishing" print "Function outer executing" print "The objects in outer's scope are:", dir() inner() print "\nFunction outer finishing" Emphasize fact that inner can be accessed only objects in the inner’s scope in function outer’s local scope print "The objects in the global scope are:" print dir() print "\nCalling function outer\n" outer() print "\nFunction outer finished" 2002 Prentice Hall. All rights reserved. The objects in the global scope are: ['__builtins__', '__doc__', '__name__', 'outer'] Outline Calling function outer Function outer executing The objects in outer's scope are: ['inner'] Function inner executing The objects in inner's scope are: [] Function inner finishing Function outer finishing Function outer finished 2002 Prentice Hall. All rights reserved. 1 2 3 4 5 6 7 8 9 10 # Fig O.9: CenterLength.py # Functional definition of string justification. Function contained def centerLength( length ): Outline within function centerLength Inner function calls object’s center method CenterLength.py def centerString( stringValue ): Return centered string return stringValue.center( length ) return centerString Python 2.2b2 (#26, Nov 16 2001, 11:44:11) [MSC 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> >>> import CenterLength >>> centerString10 = CenterLength.centerLength( 10 ) >>> >>> type( centerString10 ) <type 'function'> >>> >>> centerString10( "python" ) ' python ' 2002 Prentice Hall. All rights reserved. Python 2.1.1 (#20, Jul 20 2001, 01:19:29) [MSC 32 bit (Intel)] on win32 Type "copyright", "credits" or "license" for more information. >>> >>> import CenterLength CenterLength.py:4: SyntaxWarning: local name 'length' in 'centerLength' shadows use of 'length' as global in nested scope 'centerString' def centerLength( length ): >>> >>> centerString10 = CenterLength.centerLength( 10 ) >>> centerString10( "python" ) Traceback (most recent call last): File "<stdin>", line 1, in ? File "CenterLength.py", line 7, in centerString return stringValue.center( length ) NameError: global name 'length' is not defined Outline Fig. O.10 Nested scopes and older versions of Python. 2002 Prentice Hall. All rights reserved.