Friday, December 23, 2011

Computational economics Lecture 2


First Steps

Once you're familiar with Python, you will find that it's a joy to use
Beautifully designed by a whole lot of very smart people, evolving over many years
However, for the first few hours, Python will feel alien and confusing
Make sure you set aside a few quiet hours to learn how to start Python up and run some basic scripts
The next couple of lectures will give you some guidance
  • But don't give up if things don't work the first time
  • Remember: Google is your friend

Notes on installation

Please read through all these notes before you go ahead and install!!
The standard Python distribution can be found at python.org
However, if you are running Windows
  • The best choice is probably Python(x,y)
    • Includes many tools for scientific work
    • Windows-centric
    • See the documentation (or Google) for info on how to get started
      • This video looks helpful
If you're running Linux or Mac OS then Python is probably installed already
  • Open up a terminal and type python
  • Consider upgrading to the latest 2.x
If you install the standard Python distribution from python.org
  • Make sure you choose the 2.x series of Python, rather than 3.x!!
    • 3.x breaks backwards compatability, and most libraries haven't updated yet
    • These lectures assume that you are using 2.x

The Interpreter as a Calculator

When you start Python, the Python "shell" will greet you with a promp like so
>>>
The shell is a command line interface which provides access to the Python interpreter
We can work interactively with the shell, or with files (scripts)
For now let's work directly with the shell:
>>> 3 * 3
9
>>> 3 * 4 + 1    # Multiplication has 'precedence' over addition/subtraction
13
>>> 3 * (4 + 1)  # Term in brackets evaluated first
15
>>> 2**3         # Exponentiation
8
>>> 2^3          # Not exponentiation!
1
>>> 2**3 * 5     # Exponentiation has precedence over multiplication
40
Anything after # is ignored
  • These are comments
  • Only for human readers
Conventions:
  • Use spaces around all operators (2 * 3, not 2*3)
  • Except for exponentiation (2**3, not 2 ** 3)
So far we are working with integers
>>> type(3)   # type(x) returns the type of object x
<type 'int'>
>>> type(7)
<type 'int'>
>>> 
We can also use floating point numbers (floats), which represent real numbers
>>> type(3.0)
<type 'float'>
>>> type(7.1)
<type 'float'>
>>> 3.0 * 2.0
6.0
>>> 3.1 * 2.0
6.2000000000000002
>>> 3.1 * 2      # Mix of float and int: int is upgraded to a float
6.2000000000000002
Why 6.2000000000000002, instead of 6.2? Is this an error?
  • The problem is that floats are stored internally in binary, not decimal
  • The number 6.2 (in decimal) is recurring in binary form
  • Need an infinite sequence of zeros and ones to represent it
  • But your computer memory is finite, so this is impossible
  • Hence approximated by a finite number of bits
  • This approximation error is observable when you convert back to decimal
  • Some computer programs hide this from you, but Python does not
Warning: For floats and integers, division is different!
Examples:
>>> 5 / 2      # Integer division returns the integer part only
2
>>> 5.0 / 2.0  # Float division returns the full (floating point) solution
2.5
>>> 5.0 / 2    # Mixed, so 2 upgraded to float
2.5
>>> 
  • This mimics older languages like C, but it's now recognized as a design flaw
  • Fixed in Python 3.x
  • You can get proper division as follows
>>> from __future__ import division
>>> 5 / 2
2.5
>>> 1 / 2
0.5
Note that we can convert from one numeric type to another explicitly:
>>> float(3)
3.0
>>> int(3.5)
3
>>> float(5) / 2
2.5

Variables

Variables are names associated with objects (e.g. integers, floats)

Assignment

To associate the name x to the object 1, type
>>> x = 1
x is also called an identifier
We say that identifier x is bound to the object 1
To see the value of x (the object to which it is bound) type
>>> print x
1
Or just
>>> x
1
Note that Python is case sensitive: X and x are different
>>> x = 1
>>> X
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'X' is not defined
Some more examples
>>> x = 3          # Bind x to integer 3
>>> y = 2.5        # Bind y to floating point number 2.5
>>> print x * y
7.5
>>> z = x * y      # Bind z to x * y = 7.5
In the last line, Python evaluated the RHS and bound z to the result
Another example:
>>> x = x + 1      # Rebind x to integer 4
>>> print x
4
Multiple assignment on one line:
>>> a, b, c = 1, 2, 3    # Bind a to 1, b to 2, etc.
This is okay too
>>> x = y = 1

Restrictions on Names

Identifiers (names) can include numbers, but not at start:
>>> a1 = 10
>>> 1a = 10
  File "<stdin>", line 1
    1a = 10
     ^
SyntaxError: invalid syntax
>>> 
SyntaxError means that the syntax not valid
Also, must avoid Python keywordsand, del, from, not, while, as, elif, global, or, with, assert, else, if, pass, yield, break, except, import, print, class, exec, in, raise, continue, finally, is, return, def, for, lambda, try
>>> and = 3
  File "<stdin>", line 1
    and = 3
      ^
SyntaxError: invalid syntax

Strings

So far we have looked at two numeric data types: integers and floats
Strings are another primitive data type in Python
  • Used to store and represent text
>>> s = 'hello world'   # Bind identifier s to the string 'hello world'
>>> s
'hello world'
>>> s = "hello world"   # Double quotes okay
>>> s
'hello world'
>>> type(s)
<type 'str'>
We can insert a newline character into a string with \n:
>>> s = 'hello \nworld'
>>> s
'hello \nworld'
>>> print s
hello 
world
We can also create multiline strings using triple quotes:
>>> s = """hello   # Hit return and three dots appear on next line
... world"""
>>> s
'hello\nworld'
Individual characters can be accessed by their index, starting from zero:
>>> s = 'foo'
>>> s[0]
'f'
>>> s[1]
'o'
>>> s[2]
'o'
>>> s[3]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: string index out of range
Strings consisting of numbers can be converted into floats or ints
>>> s = '1'      # Can be converted into an integer or float
>>> type(s)
<type 'str'>
>>> int(s)
1
>>> float(s)
1.0
>>> s = 'foo'    # But not this one
>>> int(s)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'foo'
Conversely, we can convert numbers into strings using str()
>>> str(3.2)
'3.2'
>>> str(1)
'1'

Lists and Tuples

Another data type is a list, used to store a collection of other data types
>>> x = [10, 20, 100]            # Elements can be numbers
>>> x
[10, 20, 100]
>>> y = ['hello ', 'world']      # Or strings....
>>> y
['hello ', 'world']
>>> z = [x, y]                   # Or any type, in fact, including lists
>>> z
[[10, 20, 100], ['hello ', 'world']]
>>> type(x)
<type 'list'>
>>> type(y)
<type 'list'>
>>> type(z)
<type 'list'>
Elements can be accessed by their index, starting from zero:
>>> x = [10, 100, 1000]
>>> x[0]
10
>>> x[1]
100
>>> x[2]
1000
>>> y = [[10, 100], [-10, -100]]
>>> y
[[10, 100], [-10, -100]]
>>> y[0]
[10, 100]
>>> y[0][1]
100
We can change the elements of a list using the index:
>>> x = [20, 30]
>>> x[0] = 'foo'
>>> x
['foo', 30]
>>> x[1] = 'bar'
>>> x
['foo', 'bar']
>>> x[2] = 'spam'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range
And we can delete by index with del
>>> Y = ['a', 'b', 'c', 'd']
>>> del Y[0]
>>> Y
['b', 'c', 'd']
In contrast, strings are immutable, so we cannot change by index:
>>> s = 'foo'
>>> s[0] = 'g'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment
>>> del s[0]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object doesn't support item deletion
Tuples are another data type for storing collections
  • Like a list
  • But immutable
  • Use round brackets instead of square:
>>> x = (10, 20)
>>> x
(10, 20)
>>> type(x)
<type 'tuple'>
>>> x[0]
10
>>> x[1]
20
>>> x[0] = 'foo'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
For tuples, brackets are optional
>>> x = 10, 20
>>> x
(10, 20)
>>> type(x)
<type 'tuple'>
Why do we need both tuples and lists?
As we will see later, sometimes it's useful to be immutable

More Sequence Operations

Data types which can be indexed from zero are called sequences
  • Lists, tuples and strings are all sequences
Sequences can be concatinated using +
>>> 'spam' + ' and eggs'
'spam and eggs'
>>> s = 'spam'
>>> t = ' and eggs'
>>> s + t
'spam and eggs'
>>> (2, 3) + (4, 5)
(2, 3, 4, 5)
>>> ['a', 'b'] + [1, 2]
['a', 'b', 1, 2]
Multiplication means repetition:
>>> 'foobar' * 4
'foobarfoobarfoobarfoobar'
>>> (2, 3) * 4
(2, 3, 2, 3, 2, 3, 2, 3)
>>> ['a', 'b'] * 3
['a', 'b', 'a', 'b', 'a', 'b']
All sequences can be unpacked
>>> a, b, c = 'foo'
>>> a
'f'
>>> b
'o'
>>> c
'o'
>>> x, y = [10, 100]
>>> x
10
>>> y
100
>>> x, y = (10, 100)
>>> x
10
>>> y
100
>>> x, y = 10, 100
>>> x
10
>>> y
100
Slices are used to select multiple contiguous elements of the sequence
>>> X = ('a', 'b', 'c', 'd')
>>> X[1:3]
('b', 'c')
Note that the right hand side is not inclusive.
  • Think of it like a left-closed, right-open interval [n,m)
Here are some more examples
>>> X = ('a', 'b', 'c', 'd')
>>> X[1:]  
('b', 'c', 'd')
>>> X[:2]
('a', 'b')
>>> X[:]
('a', 'b', 'c', 'd')
>>> S = 'foo'
>>> S[1:]
'oo'

Methods

Methods are actions we can call on objects such as strings and lists
Here's an example of a string method
>>> s = 'foo'
>>> S = s.upper()
>>> S
'FOO'
>>> s  # Note that s itself is unchanged (it is immutable!)
'foo'
Here are some more examples of string methods
>>> s.capitalize()
'Foo'
>>> s.startswith('f')
True
>>> s.startswith('fa')
False
>>> s.count('f')    # Count number of times 'f' occurs in s
1
>>> s.replace('o', 'e')
'fee'
There are many more string methods
One more worth mentioning is split()
>>> t = 'foo bar'
>>> t.split()     # Makes a list of words (splits at each space)
['foo', 'bar']
>>> t = 'foo,bar'
>>> t.split()     # Doesn't work, because there's no space
['foo,bar']
>>> t.split(',')  # Split at each comma
['foo', 'bar']
Next let's look at list methods
>>> X = [10, 100, 1000]
>>> X.append(10000)    # Append to the end of X
>>> X
[10, 100, 1000, 10000]
>>> X.pop()            # Remove the last element and return it
10000
>>> X
[10, 100, 1000]
>>> X.index(10)        # What is the index of 10?
0
>>> X.index(100)
1
>>> X.reverse()        # Reverses X
>>> X
[1000, 100, 10]
>>> X.remove(100)      # Remove the first instance of 100
>>> X
[1000, 10]
There are many more list methods (see the Python documentation)
Common syntax for method calls: identifier.methodName(methodArguments)
>>> t.split(',')  # identifier.methodName(methodArguments)

Built-in Functions

Python provides some useful built-in functions
You have already met type()int()float() and str()
Here are a few more of them
>>> abs(-1.0)
1.0
>>> max([1, 2, 3, 2, 1])
3
>>> min([1, 2, 3, 2, 1])
1
>>> sum([1, 2, 3, 2, 1])
9
>>> len([1, 2, 3, 2, 1])   # Returns the length of the sequence
5
>>> len('foo')
3
>>> range(5)               # Returns indices of a sequence with 5 elements
[0, 1, 2, 3, 4]
Try not to shadow built-in function names with variable name declarations:
>>> max
<built-in function max>
>>> max([1, 2, 3])
3
>>> max = 7           # The name max is bound to the integer 7
>>> max
7
>>> max([1, 2, 3])    # Error: 7([1, 2, 3]) does not make sense
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'int' object is not callable
An elementary way to obtain input from the user is with raw_input()
>>> firstname = raw_input("What is your first name? ")
What is your first name? John
>>> surname = raw_input("What is your surname? ")
What is your surname? Stachurski
>>> fullname = firstname + ' ' + surname
>>> fullname
'John Stachurski'
  • Note that the return value is a string
  • The related function input() should be avoided for security reasons

List Comprehensions

List comprehensions are a way to build lists
One of the many nice features of Python
>>> X = 1, 2, 3, 4            # X is a tuple
>>> Y = [x * 2 for x in X]    # Y is a list built from a list comprehension
>>> Y
[2, 4, 6, 8]
What happens here?
  • First, x is bound to X[0]
    • That is, x is bound to the integer object 1
  • Then x * 2 is evaluated, and result becomes first element of Y
  • Next, x is bound to the second element of X...
Note that the choice of identifier x was arbitrary:
>>> Y = [anyname * 2 for anyname in X]   #  The variable name is arbitrary
>>> Y
[2, 4, 6, 8]
List comprehensions can step through the elements of any sequence type (tuple, list, string, etc.)
>>> word = 'foo'
>>> Y = [letter.upper() for letter in word]
>>> Y
['F', 'O', 'O']
The object created by a list comprehension is always a list


0 comments: