Chapter 3: Notes on “Dive Into Python” by Mark Pilgrim

April 22nd, 2009 | No Comments »

Note: I’m currently in the process of learning Python.  These are notes on “Dive Into Python” by Mark Pilgrim (also available online), an excellent book if you’re like me and learn by the “do first, understand later” method.

In Chapter 3, Mark introduces:

Dictionaries

A dictionary defines a one-to-one relationship between a key and a value.  Here’s how you define a dictionary:

>>> d = {"firstname":"lee","lastname":"clemmer","age":"26"}

To access the value of a specific key:

>>> d["firstname"]
'lee'

Note, however, that you cannot get keys by values:

>>> d["clemmer"]

Traceback (most recent call last):
  File "<pyshell#22>", line 1, in <module>
    d["clemmer"]
KeyError: 'clemmer'

To add a key:

>>> d["hometown"] = "Bremen"
>>> d
{'lastname': 'clemmer', 'age': '26', 'firstname': 'lee', 'hometown': 'Bremen'}

To overwrite a key:

>>> d["age"] = "21"
>>> d
{'lastname': 'clemmer', 'age': '21', 'firstname': 'lee', 'hometown': 'Bremen'}

Note that this is the same syntax as adding a key.

To delete a key:

>>> del d["age"]
>>> d
{'lastname': 'clemmer', 'firstname': 'lee', 'hometown': 'Bremen'}

To clear the whole dictionary:

>>> d.clear()
>>> d
{}

Important to note:

  • Dictionaries are unordered.  This is why the sequence they appear in seems random.  It is.  They’re not “out of order”, there is no order.
  • Dictionaries cannot have duplicate keys
  • Dictionary keys are case-sensitive: d["key"] and d["Key"] are different
  • Dictionary values can be of any datatype (strings, integers, objects, dictionaries, etc.)
  • Dictonary keys can only be certain datatypes (immutables, like strings, integers, or tuples of immutables)
  • Both key and value datatypes can be mixed and matched within a single dictionary

Dictionary have a built-in function that returns a list of tuples of all or some of the data in the dictionary:

>>> d.keys()
['lastname', 'age', 'firstname']
>>> d.values()
['clemmer', '26', 'lee']
>>> d.items()
[('lastname', 'clemmer'), ('age', '26'), ('firstname', 'lee')]

Although dictionaries are unordered, note that d.values()[n] == d.keys()[n] for all values of n.

Further reading on dictionaries:

Lists

Top

Lists are ordered sets of elements, as opposed to unordered dictionaries.  They are similar to zero-based arrays.

To create a list:

>>> list = ["1", 2, "three", 4, "lee"]
>>> list
['1', 2, 'three', 4, 'lee']

As you can see, I’ve mixed and matched strings and integers.

To access one of the elements, you indicate its position, with the first one being 0:

>>> list[0]
'1'
>>> list[3]
4

You can also use a negative index to access elements.  The last element always corresponds to -1, or li[-n] == li[len(li) - n]:

>>> list[-1]
'lee'
>>> list[-5]
'1'

You can slice a list by specifying the first index and the index after the last element you want returned, which is a bit counterintuitive.  For example:

>>> list = ["one", "two", "three", "four", "five"]
>>> list
['one', 'two', 'three', 'four', 'five']
>>> list[1:3]
['two', 'three']
>>> list[-4:-1]
['two', 'three', 'four']
>>> list[:3]
['one', 'two', 'three']
>>> list[3:]
['four', 'five']
>>> list[:]
['one', 'two', 'three', 'four', 'five']

Some notes about these examples:

  • [1:3] specifies element at index [1] (‘two’) until element at index before [3], i.e. [2] (‘three’)
  • Negative indices work as well
  • You can use shorthand: [:3] implies “start from index [0]“; [3:] implies “until last index”
  • [:] returns all list elements as a copy of that list

There are several different ways to add elements onto or into a list:

>>> list
['one', 'two', 'three', 'four', 'five']
>>> list.append("seven")
>>> list
['one', 'two', 'three', 'four', 'five', 'seven']
>>> list.insert(5,"six")
>>> list
['one', 'two', 'three', 'four', 'five', 'six', 'seven']
>>> list.extend(["eight","nine"])
>>> list
['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
  •  append adds a single element to the end of list
  • insert inserts an element and bumps up the element referenced in the call ([5] in the example: it inserted the string “six” in the sixth position at index [5])
  • extend concatenates lists; you call it with one list as the argument as opposed to multiple arguments.  This adds each list element as a new element.  If you were to do append(["one","two"]) this would append a list as one element

To query the length of a list, simply:

>>> len(list)
9

To search for the index of an element:

>>> list.index('four') 3 >>> list.index('ten') Traceback (most recent call last): File "<pyshell#82>", line 1, in <module> list.index('ten') ValueError: list.index(x): x not in list >>> "ten" in list False 
  • index returns the index of the first occurrence of an element
  • search for an element that doesn’t exist raises an exception and crashes your program (instead of returning in invalid index)
  • to see if a value is present in a list, use in, which will return True or False

To delete an element from a list:

>>> list
['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine']
>>> list.remove('three')
>>> list
['one', 'two', 'four', 'five', 'six', 'seven', 'eight', 'nine']
>>> list.remove('three')

Traceback (most recent call last):
  File "<pyshell#99>", line 1, in <module>
    list.remove('three')
ValueError: list.remove(x): x not in list
>>> list.pop()
'nine'
>>> list
['one', 'two', 'four', 'five', 'six', 'seven', 'eight']
  • remove removes only the first occurrence of the given value
  • if the value isn’t found, Python raises an exception
  • pop does two things
    1. removes the last element
    2. returns that element

There are a number of different operators that you can use on lists:

>>> list = ["one", "two"]
>>> list = list + ["three", "four"]
>>> list
['one', 'two', 'three', 'four']
>>> list += ["five"]
>>> list
['one', 'two', 'three', 'four', 'five']
>>> list *= 3
>>> list
['one', 'two', 'three', 'four', 'five', 'one', 'two', 'three', 'four', 'five', 'one', 'two',
'three', 'four', 'five']
>>> list = [1,2] * 4
>>> list
[1, 2, 1, 2, 1, 2, 1, 2]
  • The + operator concatenates two lists into a new list. This is the same as the extend function, except that concatenation creates a new string, where as extend just extends an existing string, making it much faster, especially for large lists.
  • list += ["five"] is the same as list = list + ["five"] or list.extend(["five"])
  • The * operator acts as a repeater on a list

Further reading on lists:

Mapping Lists

List comprehension provides a way to map a list onto another list.  Note that this does not change the original list, unless you assign it as such:

>>> list = ["item 1", 2, "three", 4]
>>> [elem*2 for elem in list]
['item 1item 1', 4, 'threethree', 8]
>>> list
['item 1', 2, 'three', 4]
>>> list = [elem*3 for elem in list]
>>> list
['item 1item 1item 1', 6, 'threethreethree', 12]

Further reading on list comprehension

Tuples

Top

A tuple is an immutable list.  That would be a list that you can’t change.  Once it’s created, you can’t change it. It’s immutable.  However, other than not changing, it acts very much like a list:

>>> t = ("lee","clemmer")
>>> t
('lee', 'clemmer')
>>> t[1]
'clemmer'
>>> t[:1]
('lee',)
>>> t[-2]
'lee'
>>> t.remove("clemmer")

Traceback (most recent call last):
  File "<pyshell#122>", line 1, in <module>
    t.remove("clemmer")
AttributeError: 'tuple' object has no attribute 'remove'
>>> t.pop()

Traceback (most recent call last):
  File "<pyshell#123>", line 1, in <module>
    t.pop()
AttributeError: 'tuple' object has no attribute 'pop'
>>> t.append("albert")

Traceback (most recent call last):
  File "<pyshell#124>", line 1, in <module>
    t.append("albert")
AttributeError: 'tuple' object has no attribute 'append'
>>> t.insert("albert")

Traceback (most recent call last):
  File "<pyshell#126>", line 1, in <module>
    t.insert("albert")
AttributeError: 'tuple' object has no attribute 'insert'

As you can see, defining a tuple and calling an element thereof is very much like working with lists. However, trying to change it throws an exception.  Tuples have no methods.

Why use a tuple? It’s faster.  Therefore, use tuples for constants that don’t change.

Further reading on tuples:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Declaring Variables

Top

Python has local and global variables, but doesn’t explicitly declare variables.  A variable is created when you assign a value to it, and is destroyed once out of scope.  You cannot reference a variable that hasn’t been assigned a value (and hence doesn’t exist):

>>> myParams = { "firstname":"lee",
	     "lastname":"clemmer",
	     "age":"26"}
>>> myParams
{'lastname': 'clemmer', 'age': '26', 'firstname': 'lee'}
>>> x

Traceback (most recent call last):
  File "<pyshell#7>", line 1, in <module>
    x
NameError: name 'x' is not defined
>>> x = 1
>>> x
1

When creating variables, you can assign multiple values to variables at once:

>>> numbers = (1,2,3)
>>> numbers
(1, 2, 3)
>>> (x,y,z) = numbers
>>> x
1
>>> y
2
>>> z
3
>>> (a,b,c,d) = numbers

Traceback (most recent call last):
  File "<pyshell#16>", line 1, in <module>
    (a,b,c,d) = numbers
ValueError: need more than 3 values to unpack

As you can see by the last example, the number of variables have to match the number of elements in the tuple, list, or dictionary.  You can also assign variables using the range function:

>>> (one, two, three, four) = range(4)
>>> one
0
>>> two
1
>>> three
2
>>> four
3

For more information on range:

>>> print range.__doc__
range([start,] stop[, step]) -> list of integers

Return a list containing an arithmetic progression of integers.
range(i, j) returns [i, i+1, i+2, ..., j-1]; start (!) defaults to 0.
When step is given, it specifies the increment (or decrement).
For example, range(4) returns [0, 1, 2, 3].  The end point is omitted!
These are exactly the valid indices for a list of 4 elements.
>>> range(1,100,3)
[1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 52,
55, 58, 61, 64, 67, 70, 73, 76, 79, 82, 85, 88, 91, 94, 97]

Further reading on variables:

Formatting Strings

Top

Python allows you to format values into strings, for example by using the string placeholder %s:

>>> x = "a string"
>>> y = "another string"
>>> "%s and %s" % (x,y)
'a string and another string'

Importantly, the expression evaluates to a string.  This implies that you can coerce types into strings.

This kind of string formatting allows you to “join” a string and, say, a number, which you normally couldn’t concatenate:

>>> x = "you can concatenate "
>>> y = "two strings"
>>> print x + y
you can concatenate two strings
>>> "%s%s like this also" % (x,y)
'you can concatenate two strings like this also'
>>> number = 2
>>> print x + number + " a string and number - not!"

Traceback (most recent call last):
  File "<pyshell#15>", line 1, in <module>
    print x + number + " a string and number - not!"
TypeError: cannot concatenate 'str' and 'int' objects
>>> "%s%d different types like so - to make a string" % (x,number)
'you can concatenate 2 different types like so - to make a string'

You can also work with floats:

>>> print "This is a float: %f" % 3.1425
This is a float: 3.142500
>>> print "To control decimal places: %.2f" % 3.1425
To control decimal places: 3.14
>>> print "How about a +/- sign: %+.2f" % -3.1425
How about a +/- sign: -3.14

Further reading on formatting strings:

Joining Lists and Splitting Strings

All strings are themselves objects, and as such have a built-in join() function.  The join function takes a list and joins its elements into a single string, separated by the string that made the join call:

>>> list
['Monday', 'Tuesday', 'Make sense?']
>>> " is a day. ".join(list)
'Monday is a day. Tuesday is a day. Make sense?'

You can also reverse this using split():

>>> sentences = " is a day. ".join(list)
>>> sentences
'Monday is a day. Tuesday is a day. Make sense?'
>>> sentences.split(" is a day. ")
['Monday', 'Tuesday', 'Make sense?']
>>> list
['Monday', 'Tuesday', 'Make sense?']
>>> sentences.split(" is a day. ", 1)
['Monday', 'Tuesday is a day. Make sense?']

The last example shows that split takes an optional argument, in this case how many times the split should occur.

Further reading on string methods:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Top



Leave a Reply