Logo
  • Home
  • Classes
  • Conveying Computing
  • Exams
  • Fractal Gallery
  • Guides
  • Problem Sets
  • Syllabus

Schemer’s Guide to Python

Python, a reference to Monty Python's Flying Circus, is an open-source scripting language that is extremely flexible and powerful. Python is a server-side language, meaning that python programs run on the web server in response to a user request to produce an output web page.

This document should provide enough information to get started writing Python programs (and to complete Problem Sets 6 and 7), but you may need to consult the online Python documentation (available at http://www.python.org/doc/) to find out about other useful primitive procedures in Python.

Installing and Using Python

Download Python Version 2.7.2 from: http://www.python.org/download/. (Note: do not use Python Version 3.X, it is not compatible with some of the programs we will use.)

Installers are available for many platforms including Windows, MacOS X 10.6/10.7, MacOX X 10.3-10.6, and a compressed tarball for Unix platforms.

The Python distribution includes an interactive editing environment, IDLE. Once you have installed Python, you can start IDLE directly or (in Windows) by right-clicking on a Python file (ending with extension .py) and selecting "Edit with IDLE". Working with IDLE is fairly similar to using DrRacket, except instead of splitting one window the declaractions and interactions are done in separate windows. If you are in an edit window, selecting Run Module from the Run menu (or F5) loads your file into the interactions window (which is called "Python Shell"). At the prompt, you can interactively evaluate Python commands, similarly to how you evaluate Scheme expressions in the DrScheme interactions window.

We recommend you download, install, and start running Python now, and try out the examples in this guide yourself.

Programming in Python

Python is a universal programming language — this means every process we could describe using a Turing Machine (or using Scheme), we can also describe in Python. The syntax of Python is very different from Scheme, but most of the evaluation rules are quite similar.

All Python code is a sequence of statements separated by newlines:

PythonCode ::= Statements
Statements ::= Statement <newline> Statements
Statements ::=

Note that unlike in Scheme, whitespace (such as new lines) has meaning in Python. Statements cannot be separated into multiple lines, and only one statement may appear on a single line. Indentation within a line also matters. Instead of using parentheses to provide code structure, Python uses the indentation to group statements into blocks.

Python has many different kinds of statements. The three you will use most are assignment, applications and function definitions:

Statement ::= AssignmentStatement
Statement ::= ApplicationStatement
Statement ::= FunctionDefinition

Assignment

Scheme is designed for a functional programming style. This means most of a Scheme program is applying and defining functions (and procedures).

Python is designed for an imperative programming style (although one of the best features of Python is it also provides good support for functional programming). This means most of a Python program is assignments.

In Scheme, the set! special form performs an assignment. In Python, the = sign means assignment (to do equality comparisons, Python uses ==):

AssignmentStatement ::= Variable = Expression

To evaluate an AssignmentStatement, Python evaluates the Expression and places the value in the place named Variable, similar to the Scheme evaluation rule for set!).

Unlike the Scheme set!, if there is not already a place named Variable, Python will create a new place as part of evaluating the assignment statement. Hence, the Python statement x = 1 will act like (define x 1) if there is no place already named x, and like (set! x 1) if there is already a place named x.

An expression in Python is similar to an expression in Scheme — it is a code fragment that evaluates to a value. In Python, expressions use infix notation. The operator is placed between the operands (except for function calls, described below). Python supports most of the standard arithmetic operators. Here are some examples:

SchemePython
(define four 4)
(define two (/ four 2))
(define bigger (< (* four four) 17)
four = 4
two = four / 2
bigger = (four * four) < 17

The parentheses in the assignment to bigger are necessary for grouping oprations. Without them,

   
   four * four < 17
would mean (* four (< four 17)) instead of (< (* four four) 17).

Applications

In Python, we apply a function to operands by following the name of the function with a comma-separated list of arguments surrounded by parentheses:
ApplicationStatement ::= Name ( Arguments )
Arguments ::=
Arguments ::= MoreArguments
MoreArguments ::= Argument ,MoreArguments
MoreArguments ::= Argument
Argument ::= Expression

So, Proc(Arguments) in Python is similar to (Proc Arguments) in Scheme (except there are no commas between the arguments in Scheme).

Defining Procedures

Defining a procedure in Python is similar to in Scheme, except:
  • instead of using lambda to make a procedure, you can define a procedure by listing the parameters after the function name
  • instead of just evaluating to a value, you must use return to explicitly output a result

We define a function using:

FunctionDefinition ::= def Name (Parameters ): <newline> Statements
Parameters ::=
Parameters ::= MoreParameters
MoreParameters Parameter ,MoreParameters
MoreParameters ::= Parameter
Parameter ::= Variable

For example,

SchemePython
(define tautology (lambda () true))
(define square
   (lambda (x) (* x x)))
(define quadratic (lambda (a b c x)
   (+ (* a (square x)) (* b x) c)))

(quadratic 2 3 7 4)

51

def tautology (): return True
def square (x):
   return x * x
def quadratic (a, b, c, x):
   return a * square (x) + b * x + c

quadratic (2,3,7,4)

51

Note that unlike Scheme, where the procedure body is an expression and the value of an application is the value of that expression (evaluated in the new environment with the parameters bound), in Python, the procedure body is a list of Statements. The special statement,

ReturnStatement ::= return Expression

is used to return a value from a procedure. When a return statement is evaluated, the Expression is evaluated and returned to the caller.

Python also provides a lambda expression for making new procedures similiar to Scheme's lambda expression:

Expression ::= lambda Parameters : Expression
The parameters are defined as above (a comma-separated list of names with no parentheses around them), and the body is the one expression (a return before the expression is implied). For example, (lambda (a b) (+ a b)) would be lambda a, b: a + b. Here's an example:

def makeAdder (a): return lambda b: a + b

add5 = makeAdder (5)

add5(2)

7

Python does not evaluate applications the same way as Scheme, however. In particular, Python does not create a chain of frames for evaluation purposes. Instead, there are only two namespaces (Pythonspeak for frames): the global namespace and the local namespace.

Control Statements

Python also provides several statements similar to Scheme special forms. Two useful ones are if and while which are described below.

If

The if statement is similar to Scheme's if special form:
Statement ::= if Expression: Block

is equivalent to (if Expression (begin Statements)).

Python also supports alternative clauses but uses else to distinguish them:

Statement ::= if Expression: BlockConsequent
                     else: BlockAlternate
is similar to (if Expression (begin Statements1) (begin Statements2)).

While

The while statement repeats a sequence of statements as long as the test expression is true:
Statement ::= while Expression: Block

The indentation of the statements determines the statements that are included in the while body.

Here is an example that will print out the first 10 Fibonacci numbers:

i = 1;
a = 1;
b = 1;
while (i <= 10):
  print "Fibonacci %s = %s" % (i,b);
  next = a + b;
  a = b;
  b = next;
  i = i + 1;
print "Done."

Types

Like Scheme, Python has latent (invisible) types that are checked dynamically. The five types you will find most useful are Booleans, numbers, strings, lists, and dictionaries.

Booleans

Python uses True to mean true (note that capitalization matters), and False to mean false.

Python considers the empty string, 0, and the empty list to be false, and (almost) everything else true. So,

if 0: 3
else: 4
evaluates to 4, and
if 1: 3
else: 4
evaluates to 3.

Numbers

Python treats numbers similarly to Scheme, except it does not do exact arithmetic.

Instead of using fractions, everything is treated as either an integer or a floating point number. Here are some examples:

SchemePython
(define four 4)
(define pi 3.14159)
(define half 1/2)
four = 4
pi = 3.14159
nothalf = 1/2     (evaluates to 0)
half = 1.0/2.0     (evaluates to .5)

What happened when we defined nothalf?

Unlike Scheme, Python makes a distinction between integer math and floating point math. This normally isn't that important; when we do math between the same types, the result is the same type, and when we do math with a floating point number and an integer, the type returned is a floating point number. However, the result of division of an integer by another integer is not necessarily an integer — Python will silently discard the fractional part of the answer. By writing the operands with decimal points, we ensure that the operation will return a floating point number. This problem only rarely occurs, but can cause difficult to find bugs when it does.

Strings

Python treats strings like Scheme: they need quotation marks. You can use single quotes ('), double quoteS ("), or triple quotes (""").

However, there is an important difference between triple quotes and other quotes: when you use triple quotes you can break lines in the string, but when you use single or double quotes you cannot split the string into multiple lines.

You can concatenate (run together) two strings by using the plus sign (+):

name = "Spot"
print "See " + name + " run."

If you want a literal quote to appear in a string you print, use \":

print "My name is \"Spot\"."

The triple quote, """ is an easy way to print large chunks of text that can include double quotes and new lines. For example,

print """
"I find that the harder I work, the more luck I seem to have."
   --- Thomas Jefferson
"""
will print out

"I find that the harder I work, the more luck I seem to have."
  --- Thomas Jefferson

Lists (and Tuples)

Python has its own version of lists. Although these have many things in common with Scheme lists, it's best to think of them as a different data type.

The list type is Python is mutable, so more like mlist in Scheme. The biggest difference between a Scheme mutable list and a Python list is that elements in Python lists are can be accessed directly. This means that we can access any element of the list directly if we know it's location. In Scheme, we needed to write a function to cdr down the list to find the right element.

SchemePython

> (define lst (list 10 20 30))

> (car lst)

10

> (car (cdr (cdr lst)))

30

>>> lst = [10, 20, 30]
>>> lst[0]

10

>>> lst[2]

20

Indices in Python are much more powerful than that, however. We can "slice" lists to only look at a subset of the list data. When we slice a list, the result is a new copy of the relevant parts of original list, so any modifications of the result of a slice do not impact the original list.

>>> lst = [10, 20, 40, "string", 302.234]

>>> lst[0:2]

[10, 20]

>>> lst[:3]

[10, 20, 40]

>>> lst[3:]

['string', 302.23399999999998]

(Note that decimal numbers are not exact — we put 302.234 in the list, but the printed value is 302.23399999999998.)

Finally, if we want to iterate over an entire list, we use the for statement:

Statement ::= for VaribleList in ExpressionList : Block

For example,

   def sum (lst):
      total = 0
      for el in lst:
         total = total + el
      return total

>>> sum([1, 2, 3, 4])

10

In addition to lists, Python also has a data type called a "tuple", which is almost like a list, except that it is immutable. A tuple is denoted using parentheses instead of brackets.

We can slice tuples and iterate over them, but we can't change them in place. For example, with a list we can do:

lst = [1, 2, 3, 4]
lst[2] = 5

We cannot do:

tup = (1, 2, 3, 4)
tup[2] = 5 FAILS

Why does this matter? Because there are things we can't do with lists that we can do with tuples, but other contexts where only immutable datatypes can be used. For example, as you'll see below, dictionary keys must be immutable, so we can use tuples as the dictionary keys but not lists.

List Functions

Python provides built-in procedures that work on lists and tuples similar to many of the built-in procedures for lists in Scheme. Some of these procedures (map and filter) are built-in functions that take the list as their second input. Others (e.g., append) are methods so are applied using the method syntax, list.append(arg)).

Mapping. The map procedure is similar to list-map. It takes a function as its first input, and a list (or tuple) as its second input. It outputs a new list whose elements are the result of applying the function to each element in the input list.

For example,

>>> p = [1, 2, 3, 4]

>>> map(lambda a: a + 1, p)

[2, 3, 4, 5]

Filtering. The filter procedures is similar to list-filter. It takes a function as its first input, and a list (or tuple) as its second input. It outputs a new list whose elements are the ones in the input list for which the filter function evaluates to true.

For example,

>>> filter(lambda a: a % 2 == 0, [1, 2, 3, 4, 5, 6])

[2, 4, 6]

Appending. The append method appends an element to the end of a list. This is different from the Scheme append procedure that appends two lists.

>>> p = [1, 2, 3, 4]

>>> p.append(5)

>>> p

[1, 2, 3, 4, 5]

Note that append is a method, unlike map which is a procedure. Hence, we apply it by using the method invocation syntax,object.method(parameters).)

Deleting. The remove method takes a value as its input, and removes the first element of the list matching that value. It produces no output, but mutates the list it is applied to. For example,

>>> p = [1, 2, 1, 2]

>>> p.remove(1)

>>> p

[2, 1, 2]

>>> p.remove(1)

>>> p

[2, 2]

>>> p.remove(1)

ValueError: list.remove(x): x not in list

Dictionaries

Python also has dictionaries, referred to as a hash tables or lookup tables in some other languages (also recall Class 9 on consistent hashing).

A dictionary is a list of (key, value) pairs. In Python, the key can be any "immutable" object (tuples, strings, numbers), and the value can be any Python object. We can initialize a dictionary using the initialization expression:

DictionaryInitializationStatment ::= Variable = { InitializationExpressions }
InitializationExpressions ::=
InitializationExpressions ::= InitializationExpression, InitializationExpressions
InitializationExpression ::= Expression : Expression

The expression before the : is the key, and the following expression is the associated value.

We can set the value associated with a key using a set statement:

SetStatement ::= Expression [ Expression ] = Expression

We get the value associated with a key using:

FetchExpression ::= Expression [ Expression ]

The first expression in a fetch expression must evaluate to a dictionary.

Here are some examples:

yellow = { 'red': 255, 'green': 255, 'blue': 0 }
print '(%s, %s, %s)' % (yellow['red'], yellow['green'], yellow['blue'])

(255, 255, 0)

yellow['red'] = 230 print '(%s, %s, %s)' % (yellow['red'], yellow['green'], yellow['blue'])

(230, 255, 0)

Of course, we can put arrays in arrays, just like we can make lists of lists in Scheme.

To do something to everything in the array, we first have to use the built-in "keys" method of the dictionary. For example, to reset yellow, we would do:

for key in yellow.keys():
    yellow[key] = 0

Useful operators for dictionaries include:

  • dictionary.values() — evaluates to a list of the values in the dictionary
  • dictionary.keys() — evaluates to a list of the keys in the dictionary
  • expr in dictionary — evaluates to true if there is a key in the dictionary that matches the value of expr

Classes

In Scheme, we defined objects by explicitly packaging procedures and state. Python provides classes as a way to package procedures and state. We will only scratch the surface of Python's object-oriented features here, but it is an integral part of the language.

ClassDefinition ::= class Name:
                                        FunctionDefinitions

These function definitions will form the "methods" of the class. There are lots of special methods, and we can also create our own. The only special method we'll worry about now is the __init__ method that is used when we create an instance of an object. The __init__ method is similar to the make-class methods from Chapter 10.

Here's an example:

SchemePython

(define (make-object name)
  (lambda (message)
    (case message
      ((class) (lambda (self) 'object))
      ((object?) (lambda (self) #t))
      ((name) (lambda (self) name))
      ((say)
        (lambda (self list-of-stuff)
          (if (not (null? list-of-stuff))
              (display-message list-of-stuff))
          'nuf-said))
      ((install) (lambda (self . args) 'installed))
      (else no-method))))

class my_object:
   def __init__(self, name):
      self._name = name
   def is_object(self):
      return True
   def whatclass(self):
      return type(self)
   def name(self):
      return self._name
   def say(self, lst):
      for x in lst:
         print x
   def install(self, args):
      print "Installed"

Although the differences between the two languages prevent a direct translation (for example, object and class are both reserved words in Python, and we can't have both a data item and a member function titled "name"), it is easy to see the similarities here. We don't have to use application to create a new frame in Python; the language takes care of that for us. The variable _name introduced in __init__ will be stored in a place accessible only to this object. self._name refers to the _name variable inside the object self; self is passed into any method of an object (we'll see how this works below.)

obj = my_object("bob")

obj.name()

"Bob"

obj.is_object()

True

obj.say(["hello, world"])

hello, world

In the first line, we create a new my_object, passing it the value "bob" which will be stored as the _name value. This calls the classes __init__ method. Now, whenever we type obj.method(args), the member function of my_object is called with the first argument obj and the other arguments to the function appended in a frame where this objects variables are defined.

Python provides a convenient mechanism for inheritance:

ClassDefinition ::= class SubClassName ( SuperClassName ) :
                                        FunctionDefinitions
creates a new class named SubClassName that inherits from SuperClassName.

Here's an example:

SchemePython

(define (make-lecturer name)
  (let ((super (make-object name)))
    (lambda (message)
      (if (eq? message 'lecture)
	  (lambda (self stuff)
	    (ask self 'say stuff)
	    (ask self 'say (list "you should be taking notes")))
	  (get-method super message)))))

class lecturer (my_object):
   def lecture(self, stuff):
      self.say (stuff)
      print "you should be taking notes" 

Because of Python's built in support for classes, object-oriented programs in Python are shorter and more elegant than object-oriented programs in Scheme.

Modules

Python programs are organized into separate files known as modules. Python modules may be imported using import:

   import module

For example, import place imports the module in place.py.

Each module has its own namespace. To use names in an imported module, the module name must be used. For example, if place.py defines SimPlace, to use it in the other module, we need to use place.SimPlace.

This requires more typing, but keeps the namespaces in different files separate.

When you edit a module, you need to reload it into the Python Shell. You can reload a module using reload(module). For example, reload(place).

For More Information

There are tons of Python resources available on the web.

The main documentation page is: http://www.python.org/doc/. There is also a tutorial.

This guide was created by David Faulkner, Dan Upton, and David Evans for CS150 Fall 2005.
Print Friendly Print Get a PDF version of this webpage PDF

Leave a Reply Cancel reply

You must be logged in to post a comment.

cs1120 | RSS | Comments RSS | Book | Using These Materials | Login | Admin | Powered by Wordpress