Python in 50 minutes
For more details, see the Python
tutorial.
A simple program
| |
# welcome.py
print "Welcome to Sage Days!"
|
$ python welcome.py
Welcome to Sage Days!
|
Python code is compiled into byte code, which is executed in a
Python virtual machine. But you may never know it unless you look.
|
A computation
| |
# computation.py
a = 1 + 2 ** 3
print a
|
$ python computation.py
9
|
|
Arithmetic operators: |
| + | addition |
| - | subtraction |
| * | multiplication |
| / | division |
| ** | exponentiation |
| % | modulus |
|
Everything in Python is an "object" and has a type (e.g. int, float,
string, etc). However, an object's type is a property of the object
alone and not of a variable that points to it. This is called dynamic
typing. It's a real convenience but occassionally requires a bit of
thought.
# computation.py
a = 1 + 2 ** 3
print a
a = "Now a is a string"
print a
|
$ python computation.py
9
Now a is a string
|
Anything in a line following the character "#" is ignored by
Python.
|
Data Types
| |
integers
long integers
floats (like doubles in C or Java)
strings
lists
dictionaries
files
|
The Python interpreter
| |
>>> a = 5
>>> b = 3
>>> a*b
15
>>> a%b
2
>>> a/b
1
|
Suppose we really want 5/3 = 1.666...
>>> a * 1.0 /b
1.6666666666666667
|
or
>>> float(a)/b
1.6666666666666667
|
There are operators that convert between types if you need them. A
useful one is str(a), which produces the string representation of the
object a.
>>> a = 5
>>> a = 5.01
>>> a
5.0099999999999998
>>> str(a)
'5.01'
|
Python will sometimes convert between types for us. For instance,
>>> 10**100
10000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000L
|
produces a long integer. But sometimes Python needs some help.
>>> a = 4
>>> "the value of a is " + a
Traceback (most recent call last):
File "", line 1, in ?
TypeError: cannot concatenate 'str' and 'int' objects
>>> "the value of a is " + str(a)
'the value of a is 4'
|
|
Strings
| |
Strings may be defined with either ' ' or " ".
>>> a = "hello"
>>> print a
hello
>>> a = '$\alpha$'
>>> print a
$lpha$
>>> a = r'$\alpha$'
>>> print a
$\alpha$
|
There are lots of operators for dealing with strings. How do we find
them?
>>> dir(a)
['__add__', '__class__', '__contains__', '__delattr__', '__doc__',
'__eq__', '__ge__', '__getattribute__', '__getitem__',
'__getnewargs__', '__getslice__', '__gt__', '__hash__', '__init__',
'__le__', '__len__', '__lt__', '__mod__', '__mul__', '__ne__',
'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__rmod__',
'__rmul__', '__setattr__', '__str__', 'capitalize', 'center', 'count',
'decode', 'encode', 'endswith', 'expandtabs', 'find', 'index',
'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', 'istitle',
'isupper', 'join', 'ljust', 'lower', 'lstrip', 'replace', 'rfind',
'rindex', 'rjust', 'rsplit', 'rstrip', 'split', 'splitlines',
'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper',
'zfill']
>>> help(a.replace)
Help on built-in function replace:
replace(...)
S.replace (old, new[, count]) -> string
Return a copy of string S with all occurrences of substring
old replaced by new. If the optional argument count is
given, only the first count occurrences are replaced.
>>> b = a.replace('alph', 'bet')
>>> print b
$\beta$
|
Strings are just arrays of characters. This will be useful when
dealing with lists too.
>>> a = r'$\alpha$'
>>> a[2:5]
'alp'
>>> a[:4]
'$\\al'
>>> a[2:]
'alpha$'
>>> a[-1]
'$'
>>> a[::2]
'$apa'
|
Strings are immutable; that is, they may not be modified.
>>> a[2] = 'b'
Traceback (most recent call last):
File "", line 1, in ?
TypeError: object does not support item assignment
|
|
Lists
| |
Lists are arrays, like strings, but they can hold arbitrary data
types and they may be modified
>>> a = [10, 'sage', 3.14159]
>>> a
[10, 'sage', 3.1415899999999999]
|
or
>>> a = [ ]
>>> a.append(10)
>>> a.append("sage")
>>> a.append(3.14159)
>>> a
[10, 'sage', 3.1415899999999999]
|
or
>>> a = [0]*10
>>> a
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
>>> dir(list)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__',
'__delslice__', '__doc__', '__eq__', '__ge__', '__getattribute__',
'__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__',
'__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__',
'__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',
'__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__',
'__setslice__', '__str__', 'append', 'count', 'extend', 'index',
'insert', 'pop', 'remove', 'reverse', 'sort']
|
Unlike strings, lists are mutable:
>>> a = [10, 'sage', 3.14159]
>>> a[0] = 11
>>> a
[11, 'sage', 3.1415899999999999]
|
Watch this:
>>> b = a
>>> b.pop()
3.1415899999999999
>>> a
[10, 'sage']
|
Variables are references to objects. When we say b = a, we simply
create a new reference to the same object that a references. When we
modify that object through the reference b, the changes appear under
other references as well.
If this is not the behavior we want, we need to make a copy of the object.
>>> a = [10, 'sage', 3.14159]
>>> b = a[:]
>>> b.pop()
3.1415899999999999
>>> a
[10, 'sage', 3.1415899999999999]
|
|
Dictionaries
| |
Dictionaries provide a means of storing objects by
key rather than relative position.
>>> a = { 'zero': [0, 0], 'e1': [1, 0], 'e2': [0, 1] }
>>> a
{'zero': [0, 0], 'e1': [1, 0], 'e2': [0, 1]}
>>> a['zero']
[0, 0]
|
or
>>> a = { }
>>> a['zero'] = [0, 0]
>>> a['e1'] = [1, 0]
>>> a['e2'] = [0, 1]
>>> a
{'zero': [0, 0], 'e1': [1, 0], 'e2': [0, 1]}
>>> dir(a)
['__class__', '__cmp__', '__contains__', '__delattr__', '__delitem__',
>>> '__doc__', '__eq__', '__ge__', '__getattribute__', '__getitem__',
>>> '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__',
>>> '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__',
>>> '__repr__', '__setattr__', '__setitem__', '__str__', 'clear',
>>> 'copy', 'fromkeys', 'get', 'has_key', 'items', 'iteritems',
>>> 'iterkeys', 'itervalues', 'keys', 'pop', 'popitem', 'setdefault',
>>> 'update', 'values']
>>> a.has_key('zero')
True
>>> a.has_key('e3')
False
|
Valid keys are objects that are hashable. (Unfortunately,
lists are not hashable.)
|
Conditionals
| |
>>> a = -2
>>> if a < 0:
... print 'a < 0'
... elif a > 0:
... print 'a > 0'
... else:
... print 'a = 0'
...
a < 0
|
Notice the syntax. Blocks of code are denoted by identation rather
than { ... }. A colon ends a statement before a block of code.
Also, we do not need parentheses around the logical expression.
>>> a = [3, 5, 7, 11, 13]
>>> if 2 not in a and len(a) < 10:
... a.insert(0, 2)
...
>>> a
[2, 3, 5, 7, 11, 13]
|
The values of booleans are True or False.
|
Loops
| |
>>> for x in a:
... print x
...
2
3
5
7
11
13
|
>>> a = 3.2
>>> while a > 1:
... a /= 2
...
>>> str(a)
'0.8'
|
break causes us to leave a loop immediately.
>>> a = [3, 5, 7, 11, 13]
>>> for x in a:
... if x == 7:
... print 'list contains 7'
... break
...
list contains 7
|
In the same way, continue causes us to go back to the
top of the loop immediately.
>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> for i in range(10):
... print i*i
...
0
1
4
9
16
25
36
49
64
81
|
>>> for i in range(-5, 6, 2):
... print i
...
-5
-3
-1
1
3
5
|
range generates the list before running the loop.
xrange is similar to range except that
elements in the list are generated as needed.
>>> sum = 0
>>> for x in xrange(1, 1000001):
... sum += x
...
>>> sum
500000500000
|
List comprehensions give a convenient way to create lists
>>> squares = [ x*x for x in range(0, 11) ]
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
|
|
Working with files
| |
>>> output = open('out', 'w')
>>> output.write('hello\n')
>>> output.write('there\n')
>>> output.close()
>>>
>>> input = open('out')
>>> lines = input.readlines()
>>> lines[0]
'hello\n'
>>> lines[1]
'there\n'
>>> input.close()
|
|
Functions
| |
We just added together the first million positive integers. We
can turn this into a function so that we may vary the number of terms
to add.
>>> def sum(n):
... s = 0
... for x in xrange(1, n+1):
... s += x
... return s
...
>>> sum(1000000)
500000500000
>>> sum(35)
630
|
Notice that we do not need to specify the type of the object returned
by the function.
Suppose we want to allow our function to add the integers between
a and n.
# sum.py
# Allow sum(n) to add [1, 2, 3, ... n]
# or sum(a, n) to add [a, a+1, ..., n]
def sum(*args):
if len(args) == 1:
start = 1
stop = args[0]
else:
start = args[0]
stop = args[1]
s = 0
for x in xrange(start, stop+1):
s += x
return s
print sum(1000000)
print sum(3, 4)
|
$ python sum.py
500000500000
7
|
Functions may have no arguments. In this case, you must put
() after the function's name when calling it.
>>> def f():
... print 'hi'
...
>>> f
>>> f()
hi
>>>
|
|
Scope of variables
| |
Variables inside a block of code are only visible inside
that block.
# scope0.py
def f(n):
x = 3
return x**n
print f(4)
print x
|
$ python scope0.py
81
Traceback (most recent call last):
File "scope0.py", line 6, in ?
print x
NameError: name 'x' is not defined
|
# scope1.py
x = 3
def f(n):
return x**n
print f(4)
print x
|
# scope2.py
x = 3
def f(n):
x += 1
return x**n
print f(4)
print x
|
$ python scope2.py
Traceback (most recent call last):
File "scope2.py", line 6, in ?
print f(4)
File "scope2.py", line 3, in f
x += 1
UnboundLocalError: local variable 'x' referenced before assignment
|
# scope3.py
x = 3
def f(n):
global x
x += 1
return x**n
print f(4)
print x
|
|
Classes
| |
Python is an object-oriented language so we may create our own
data types, which will hold data and allow us to access and manipulate the
data. This is a good way to get to know your self.
# Circle.py
import math
class Circle:
def __init__(self, center, radius):
self.center = center
self.radius = radius
def area(self):
return math.pi * self.radius**2
def contains(self, point):
dx = point[0] - self.center[0]
dy = point[1] - self.center[1]
return math.sqrt(dx*dx + dy*dy) < self.radius
|
>>> c = Circle([3,4], 5)
>>> c.area()
78.539816339744831
>>> c.contains([1,1])
True
>>> c.contains([-1,1])
False
>>> c.center
[3, 4]
>>> c.center = [2,3] # don't do this!
|
In general, it is better to access variables inside a class using
functions provided by the class.
# Circle.py
import math
class Circle:
def __init__(self, center, radius):
self.center = center
self.radius = radius
def area(self):
return math.pi * self.radius**2
def contains(self, point):
dx = point[0] - self.center[0]
dy = point[1] - self.center[1]
return math.sqrt(dx*dx + dy*dy) < self.radius
def getradius(self):
return self.radius
def getcenter(self):
return self.center
def setradius(self, r):
self.radius = r
def setcenter(self, c):
self.center = c
|
|
Modules
| |
# Geometry.py
import math
class Circle:
def __init__(self, center, radius):
self.center = center
self.radius = radius
def area(self):
return math.pi * self.radius**2
def contains(self, point):
dx = point[0] - self.center[0]
dy = point[1] - self.center[1]
return math.sqrt(dx*dx + dy*dy) < self.radius
class Square:
def __init__(self, ll, side):
self.lowerleft = ll
self.side = side
def area(self):
return self.side * self.side
def contains(self, point):
dx = point[0] - self.lowerleft[0]
dy = point[1] - self.lowerleft[1]
if dx < 0 or dx > side:
return False
if dy < 0 or dy > side:
return False
def unitcircle():
return Circle([0, 0], 1)
def unitsquare():
return Square([0, 0], 1)
|
Using the module
# geometrytest.py
import Geometry
square = Geometry.unitsquare()
circle = Geometry.unitcircle()
print square.area(), circle.area()
|
$ python geometrytest.py
1 3.14159265359
|
or
# geometrytest.py
from Geometry import *
square = unitsquare()
circle = unitcircle()
print square.area(), circle.area()
|
$ python geometrytest.py
1 3.14159265359
|
|
|