DekGenius.com
[ Team LiB ] Previous Section Next Section

B.2 Part II, Types and Operations

See Section 7.10 for the exercises.

  1. The basics. Here are the sort of results you should get, along with a few comments about their meaning. Note that ; is used in a few of these to squeeze more than one statement on a single line; the ; is a statement separator.

    Numbers
    
    >>> 2 ** 16              # 2 raised to the power 16
    65536
    >>> 2 / 5, 2 / 5.0       # Integer / truncates, float / doesn't
    (0, 0.40000000000000002)
    
    Strings
    
    >>> "spam" + "eggs"      # Concatenation
    'spameggs'
    >>> S = "ham"
    >>> "eggs " + S
    'eggs ham'
    >>> S * 5                # Repetition
    'hamhamhamhamham'
    >>> S[:0]                # An empty slice at the front--[0:0]
    ''
    >>> "green %s and %s" % ("eggs", S)  # Formatting
    'green eggs and ham'
    
    Tuples
    
    >>> ('x',)[0]                        # Indexing a single-item tuple
    'x'
    >>> ('x', 'y')[1]                    # Indexing a 2-item tuple
    'y'
    
    Lists
    
    >>> L = [1,2,3] + [4,5,6]            # List operations
    >>> L, L[:], L[:0], L[-2], L[-2:]
    ([1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6], [  ], 5, [5, 6])
    >>> ([1,2,3]+[4,5,6])[2:4]
    [3, 4]
    >>> [L[2], L[3]]                       # Fetch from offsets; store in a list
    [3, 4]
    >>> L.reverse(  ); L                   # Method: reverse list in-place
    [6, 5, 4, 3, 2, 1]
    >>> L.sort(  ); L                      # Method: sort list in-place
    [1, 2, 3, 4, 5, 6]
    >>> L.index(4)                         # Method: offset of first 4 (search)
    3
    
    Dictionaries
    
    >>> {'a':1, 'b':2}['b']              # Index a dictionary by key.
    2
    >>> D = {'x':1, 'y':2, 'z':3}
    >>> D['w'] = 0                       # Create a new entry.
    >>> D['x'] + D['w']
    1
    >>> D[(1,2,3)] = 4                   # A tuple used as a key (immutable)
    >>> D
    {'w': 0, 'z': 3, 'y': 2, (1, 2, 3): 4, 'x': 1}
    >>> D.keys(  ), D.values(  ), D.has_key((1,2,3))          # Methods
    (['w', 'z', 'y', (1, 2, 3), 'x'], [0, 3, 2, 4, 1], 1)
    
    Empties
    
    >>> [[  ]], ["",[  ],(  ),{  },None]         # Lots of nothings: empty objects
    ([[  ]], ['', [  ], (  ), {  }, None])
  2. Indexing and slicing. Indexing out-of-bounds (e.g., L[4]) raises an error; Python always checks to make sure that all offsets are within the bounds of a sequence.

    On the other hand, slicing out of bounds (e.g., L[-1000:100]) works, because Python scales out-of-bounds slices so that they always fit (they're set to zero and the sequence length, if required).

    Extracting a sequence in reverse—with the lower bound greater than the higher bound (e.g., L[3:1])—doesn't really work. You get back an empty slice ([ ]), because Python scales the slice limits to make sure that the lower bound is always less than or equal to the upper bound (e.g., L[3:1] is scaled to L[3:3], the empty insertion point at offset 3). Python slices are always extracted from left to right, even if you use negative indexes (they are first converted to positive indexes by adding the length). Note that Python 2.3 three-limit slices modify this behavior somewhat: L[3:1:-1] does extract from right to left.

    >>> L = [1, 2, 3, 4]
    >>> L[4]
    Traceback (innermost last):
      File "<stdin>", line 1, in ?
    IndexError: list index out of range
    >>> L[-1000:100]
    [1, 2, 3, 4]
    >>> L[3:1]
    [  ]
    >>> L
    [1, 2, 3, 4]
    >>> L[3:1] = ['?']
    >>> L
    [1, 2, 3, '?', 4]
  3. Indexing, slicing, and del. Your interaction with the interpreter should look something like the following code. Note that assigning an empty list to an offset stores an empty list object there, but assigning an empty list to a slice deletes the slice. Slice assignment expects another sequence, or you'll get a type error; it inserts items inside the sequence assigned, not the sequence itself:

    >>> L = [1,2,3,4]
    >>> L[2] = [  ]
    >>> L
    [1, 2, [  ], 4]
    >>> L[2:3] = [  ]
    >>> L
    [1, 2, 4]
    >>> del L[0]
    >>> L
    [2, 4]
    >>> del L[1:]
    >>> L
    [2]
    >>> L[1:2] = 1
    Traceback (innermost last):
      File "<stdin>", line 1, in ?
    TypeError: illegal argument type for built-in operation
  4. Tuple assignment. The values of X and Y are swapped. When tuples appear on the left and right of an assignment symbol (=), Python assigns objects on the right to targets on the left, according to their positions. This is probably easiest to understand by noting that targets on the left aren't a real tuple, even though they look like one; they are simply a set of independent assignment targets. The items on the right are a tuple, which get unpacked during the assignment (the tuple provides the temporary assignment needed to achieve the swap effect).

    >>> X = 'spam'
    >>> Y = 'eggs'
    >>> X, Y = Y, X
    >>> X
    'eggs'
    >>> Y
    'spam'
  5. Dictionary keys. Any immutable object can be used as a dictionary key—integers, tuples, strings, and so on. This really is a dictionary, even though some of its keys look like integer offsets. Mixed type keys work fine too.

    >>> D = {  }
    >>> D[1] = 'a'
    >>> D[2] = 'b'
    >>> D[(1, 2, 3)] = 'c'
    >>> D
    {1: 'a', 2: 'b', (1, 2, 3): 'c'}
  6. Dictionary indexing. Indexing a nonexistent key (D['d']) raises an error; assigning to a nonexistent key (D['d']='spam') creates a new dictionary entry. On the other hand, out-of-bounds indexing for lists raises an error too, but so do out-of-bounds assignments. Variable names work like dictionary keys; they must have already been assigned when referenced, but are created when first assigned. In fact, variable names can be processed as dictionary keys if you wish (they're made visible in module namespace or stack-frame dictionaries).

    >>> D = {'a':1, 'b':2, 'c':3}
    >>> D['a']
    1
    >>> D['d']
    Traceback (innermost last):
      File "<stdin>", line 1, in ?
    KeyError: d
    >>> D['d'] = 4
    >>> D
    {'b': 2, 'd': 4, 'a': 1, 'c': 3}
    >>>
    >>> L = [0,1]
    >>> L[2]
    Traceback (innermost last):
      File "<stdin>", line 1, in ?
    IndexError: list index out of range
    >>> L[2] = 3
    Traceback (innermost last):
      File "<stdin>", line 1, in ?
    IndexError: list assignment index out of range
  7. Generic operations. Question answers:

    • The + operator doesn't work on different/mixed types (e.g., string + list, list + tuple).

    • + doesn't work for dictionaries, because they aren't sequences.

    • The append method works only for lists, not strings, and keys works only on dictionaries. append assumes its target is mutable, since it's an in-place extension; strings are immutable.

    • Slicing and concatenation always return a new object of the same type as the objects processed:

      >>> "x" + 1
      Traceback (innermost last):
        File "<stdin>", line 1, in ?
      TypeError: illegal argument type for built-in operation
      >>>
      >>> {  } + {  }
      Traceback (innermost last):
        File "<stdin>", line 1, in ?
      TypeError: bad operand type(s) for +
      >>>
      >>> [  ].append(9)
      >>> "".append('s')
      Traceback (innermost last):
        File "<stdin>", line 1, in ?
      AttributeError: attribute-less object
      >>>
      >>> {  }.keys(  )
      [  ]
      >>> [  ].keys(  )
      Traceback (innermost last):
        File "<stdin>", line 1, in ?
      AttributeError: keys
      >>>
      >>> [  ][:]
      [  ]
      >>> ""[:]
      ''
  8. String indexing. Since strings are collections of one-character strings, every time you index a string, you get back a string, which can be indexed again. S[0][0][0][0][0] just keeps indexing the first character over and over. This generally doesn't work for lists (lists can hold arbitrary objects), unless the list contains strings.

    >>> S = "spam"
    >>> S[0][0][0][0][0]
    's'
    >>> L = ['s', 'p']
    >>> L[0][0][0]
    's'
  9. Immutable types. Either of the solutions below work. Index assignment doesn't, because strings are immutable.

    >>> S = "spam"
    >>> S = S[0] + 'l' + S[2:]
    >>> S
    'slam'
    >>> S = S[0] + 'l' + S[2] + S[3]
    >>> S
    'slam'
  10. Nesting. Here is a sample:

    >>> me = {'name':('mark', 'e', 'lutz'), 'age':'?', 'job':'engineer'}
    >>> me['job']
    'engineer'
    >>> me['name'][2]
    'lutz'
  11. Files. Here's one way to create and read back a text file in Python (ls is a Unix command; use dir on Windows):

    #File: maker.py
    file = open('myfile.txt', 'w')
    file.write('Hello file world!\n')          # Or: open(  ).write(  )
    file.close(  )                             # close not always needed
    
    #File: reader.py
    file = open('myfile.txt', 'r')
    print file.read(  )                        # Or print open(  ).read(  )
    
    % python maker.py
    % python reader.py
    Hello file world!
    
    % ls -l myfile.txt
    -rwxrwxrwa   1 0        0             19 Apr 13 16:33 myfile.txt
  12. The dir function revisited: Here's what you get for lists; dictionaries do the same (but with different method names). Note that the dir result expanded in Python 2.2—you'll see a large set of additional underscore names that implement expression operators, and support the subclassing in Part VI. The __methods__ attribute disappeared in 2.2 as well, because it wasn't consistently implemented—use dir to to fetch attribute lists today instead:

    >>> [  ].__methods__
    ['append', 'count', 'index', 'insert', 'remove', 'reverse', 'sort',...]
    >>> dir([  ])
    ['append', 'count', 'index', 'insert', 'remove', 'reverse', 'sort',...]
    [ Team LiB ] Previous Section Next Section