[Python编程(第4版)].(Programming.Python.4th.Edition).Mark.Lutz.文字版

(yzsuai) #1

Implementing Reversals


Reversal of collections can be coded either recursively or iteratively in Python, and as
functions or class methods. Example 18-23 is a first attempt at two simple reversal
functions.


Example 18-23. PP4E\Dstruct\Classics\rev1.py


def reverse(list): # recursive
if list == []:
return []
else:
return reverse(list[1:]) + list[:1]


def ireverse(list): # iterative
res = []
for x in list: res = [x] + res
return res


Both reversal functions work correctly on lists. But if we try reversing nonlist sequences
(strings, tuples, and so on), the ireverse function always returns a list for the result
regardless of the type of sequence passed:


>>> ireverse("spam")
['m', 'a', 'p', 's']

Much worse, the recursive reverse version won’t work at all for nonlists—it gets stuck
in an infinite loop. The reason is subtle: when reverse reaches the empty string (""),
it’s not equal to the empty list ([]), so the else clause is selected. But slicing an empty
sequence returns another empty sequence (indexes are scaled): the else clause recurs
again with an empty sequence, without raising an exception. The net effect is that this
function gets stuck in a loop, calling itself over and over again until Python runs out of
memory.


The versions in Example 18-24 fix both problems by using generic sequence handling
techniques much like that of the prior section’s permutation utilities:



  • reverse uses the not operator to detect the end of the sequence and returns the
    empty sequence itself, rather than an empty list constant. Since the empty sequence
    is the type of the original argument, the + operation always builds the correct type
    sequence as the recursion unfolds.

  • ireverse makes use of the fact that slicing a sequence returns a sequence of the
    same type. It first initializes the result to the slice [:0], a new, empty slice of
    the argument’s type. Later, it uses slicing to extract one-node sequences to add to
    the result’s front, instead of a list constant.


Example 18-24. PP4E\Dstruct\Classics\rev2.py


def reverse(list):
if not list: # empty? (not always [])
return list # the same sequence type


1398 | Chapter 18: Data Structures

Free download pdf