Friday, July 13, 2007

Python in Ten Minutes

Properties

Python is strongly typed (i.e. types are enforced), dynamically, implicitly typed (i.e. you don't have to declare variables), case sensitive (i.e. var and VAR are two different variables) and object-oriented (i.e. everything is an object).
Syntax

Python has no mandatory statement termination characters and blocks are specified by indentation. Indent in to begin a block, indent out to end one. Statements that expect an indentation level end in a colon (:). Comments start with the pound (#) sign and are single-line. Values are assigned with the equals sign ("="), and equality testing is done using two equals signs ("=="). You can increment/decrement values using the += and -= operators respectively. This works on many datatypes, strings included. You can also use multiple variables on one line. For example:
intMyVar = 3
intMyVar += 2
intMyVar -= 1
strMyVar = "Hello"
strMyVar += " world."
# This swaps the variables in one line(!).
intMyVar, strMyVar = strMyVar, intMyVar
Data types

The data types available in python are lists, tuples and dictionaries. Sets are available in the sets library. Lists are like one-dimensional arrays (but you can also have lists of other lists), dictionaries are associative arrays (a.k.a. hash tables) and tuples are immutable one-dimensional arrays (Python "arrays" can be of any type, so you can mix e.g. integers, strings, etc in lists/dictionaries/tuples). The first item in all array types is 0. Negative numbers count from the end towards the beginning, -1 is the last item. Variables can point to functions. The usage is as follows:
lstSample = [1, ["another", "list"], ("a", "tuple")]
lstList = ["List item 1", 2, 3.14]
lstList[0] = "List item 1 again"
lstList[-1] = 3.14
dicDictionary = {"Key 1": "Value 1", 2: 3, "pi": 3.14}
dicDictionary["pi"] = 3.15
tplTuple = (1, 2, 3)
fnVariable = len
>>> print fnVariable(lstList)
3

You can access array ranges using a colon (:). Leaving the start index empty assumes the first item, leaving the end index assumes the last item like so:
lstList = ["List item 1", 2, 3.14]
>>> print lstList[:]
['List item 1', 2, 3.1400000000000001]
>>> print lstList[0:2]
['List item 1', 2]
>>> print lstList[-3:-1]
['List item 1', 2]
>>> print lstList[1:]
[2, 3.14]
Strings

Its strings can use either single or double quotation marks, and you can have quotation marks of one kind inside a string that uses the other kind (i.e. "He said 'hello'." is valid). Multiline strings are enclosed in triple double (or single) quotes ("""). Python supports Unicode out of the box, using the syntax u"This is a unicode string". To fill a string with values, you use the % (modulo) operator and a tuple. Each %s gets replaced with an item from the tuple, left to right, and you can also use dictionary substitutions, like so:
>>>print "Name: %s\nNumber: %s\nString: %s" % (class.name, 3, 3 * "-")
Name: Poromenos
Number: 3
String: ---
strString = """This is
a multiline
string."""
# WARNING: Watch out for the trailing s in "%(key)s".
>>> print "This %(verb)s a %(noun)s." % {"noun": "test", "verb": "is"}
This is a test.
Flow control statements

Flow control statements are while, if, and for. There is no select; instead, use if. Use for to enumerate through members of a list. To obtain a list of numbers, use range(). These statements' syntax is thus:
lstRange = range(10)
>>> print lstRange
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
for intNumber in lstRange:
# Check if intNumber is one of
# the numbers in the tuple.
if intNumber in (3, 4, 7, 9):
# "Break" terminates a for without
# executing the "else" clause.
break
else:
# "Continue" starts the next iteration
# of the loop. It's rather useless here,
# as it's the last statement of the loop.
continue
else:
# The "else" clause is optional and is
# executed only if the loop didn't "break".
pass # Do nothing
if lstRange[1] == 2:
print "1 == 2"
elif lstRange[2] == 3:
print "3 == 4"
else:
print "Dunno"
while lstRange[1] == 1:
pass
Functions

Functions are declared with the "def" keyword. Optional arguments are set in the function declaration after the mandatory arguments by being assigned a default value. For named arguments, the name of the argument is assigned a value. Functions can return a tuple (and using tuple unpacking you can effectively return multiple values). Lambda functions are ad hoc functions that are comprised of a single statement. Parameters are passed by reference, but mutable types (tuples, lists, ints, strings, etc) cannot be changed. For example:
# arg2 and arg3 are optional, they have default values
# if one is not passed (100 and "test", respectively).
def fnMyFunction(arg1, arg2 = 100, arg3 = "test"):
return arg3, arg2, arg1
ret1, ret2, ret3 = fnMyFunction("Argument 1", arg3 = "Named argument")
fnVariable = lambda x: x + 1
>>> print fnVariable(1)
2
Classes

Python supports a limited form of multiple inheritance in classes. Private variables and methods can be declared by adding at least two leading underscores and at most one trailing one (e.g. "__spam"). We can also assign arbitrary variables to class instances. An example follows:
class MyClass:
varCommon = 10
def __init__(self):
self.varMyVariable = 3
def fnMyFunction(self, arg1, arg2):
return self.varMyVariable
# This is the class instantiation
>>> clsInstance = MyClass()
>>> clsInstance.fnMyFunction(1, 2)
3
# This variable is shared by all classes.
>>> clsInstance2 = MyClass()
>>> clsInstance.varCommon
10
>>> clsInstance2.varCommon
10
# Note how we use the class name
# instead of the instance.
>>> MyClass.varCommon = 30
>>> clsInstance.varCommon
30
>>> clsInstance2.varCommon
30
# This will not update the variable on the class,
# instead it will create a new one on the class
# instance and assign the value to that.
>>> clsInstance.varCommon = 10
>>> clsInstance.varCommon
10
>>> clsInstance2.varCommon
30
>>> MyClass.varCommon = 50
# This has not changed, because varCommon is
# now an instance variable.
>>> clsInstance.varCommon
10
>>> clsInstance2.varCommon
50
# This class inherits from MyClass. Multiple
# inheritance is declared as:
# class OtherClass(MyClass1, MyClass2, MyClassN)
class OtherClass(MyClass):
def __init__(self, arg1):
self.varMyVariable = 3
print arg1
>>> clsInstance = OtherClass("hello")
hello
>>> clsInstance.fnMyFunction(1, 2)
3
# This class doesn't have a .test member, but
# we can add one to the instance anyway. Note
# that this will only be a member of clsInstance.
>>> clsInstance.test = 10
>>> clsInstance.test
10
Exceptions

Exceptions in Python are handled with try-except [exceptionname] blocks:
def fnExcept():
try:
# Division by zero raises an exception
10 / 0
except ZeroDivisionError:
print "Oops, invalid."
>>> fnExcept()
Oops, invalid.
Importing

External libraries are used with the import [libname] keyword. You can also use from [libname] import [funcname] for individual functions. Here is an example:
import random
from time import clock
intRandom = random.randint(1, 100)
>>> print intRandom
64
File I/O

Python has a wide array of libraries built in. As an example, here is how serializing (converting data structures to strings using the pickle library) with file I/O is used:
import pickle
lstList = ["This", "is", 4, 13327]
# Open the file C:\binary.dat for writing. The letter r before the
# filename string is used to prevent backslash escaping.
flFile = file(r"C:\binary.dat", "w")
pickle.dump(lstList, flFile)
flFile.close()
flFile = file(r"C:\text.txt", "w")
flFile.write("This is a sample string")
flFile.close()
flFile = file(r"C:\text.txt")
>>> print flFile.read()
'This is a sample string'
flFile.close()
# Open the file for reading.
flFile = file(r"C:\binary.dat")
lstLoaded = pickle.load(flFile)
flFile.close()
>>> print lstLoaded
['This', 'is', 4, 13327]
Miscellaneous
Conditions can be chained. 1 < lst1 =" [1," lst2 =" [3,">>> print [x * y for x in lst1 for y in lst2]
[3, 4, 5, 6, 8, 10, 9, 12, 15]
>>> print [x for x in lst1 if 4 > x > 1]
[2, 3]
del lst1[0]
>>> print lst1
[2, 3]
del lst1
Global variables are declared outside of functions and can be read without any special declarations, but if you want to write to them you must declare them at the beginning of the function with the "global" keyword, otherwise Python will create a local variable and assign to that (be careful of that, it's a small catch that can get you if you don't know it). For example:
intNumber = 5
def fnMyFunction():
# This will print 5.
print intNumber
def fnOther():
# This raises an exception because the variable has not
# been assigned to before printing. Python knows that it a
# value will be assigned to it later and creates a new, local
# intNumber instead of accessing the global one.
print intNumber
intNumber = 3
def fnYetAnother():
global intNumber
# This will correctly change the global.
intNumber = 3
Epilogue

This tutorial is not meant to be an exhaustive list of all (or even a subset) of Python. Python has a vast array of libraries and much much more functionality which you will have to discover through other means, such as the excellent online book Dive into Python. I hope I have made your transition in Python easier. Please leave comments if you believe there is something that could be improved or added.

Update: This article has been Dugg. Please post a comment here if there is anything else you would like to see, (classes, error handling, anything).
Errata
Submitted by Fubar Obfusco (not verified) on Thu, 12/01/2006 - 08:47.
reply

Python is not "weakly typed". It is strongly, dynamically, implicitly typed.

"Equality testing", not "truth testing", is done with the == sign. The == operator tells you if its arguments are equal, not if they are true.

Dictionaries are not "one-dimensional named arrays". They are associative arrays, sometimes known as hash tables, although "hash table" is really the name of one implementation of associative arrays.

A useful use of the array range colon is to copy an array:

newary = oldary[:]

Multiline strings can be enclosed in '''triple single quotes''' as well as """triple double quotes""".

"Flow control statements are while, if@, and @for" contains unnecessary @ signs.

Functions returning a tuple is not the same as functions returning multiple values. You're thinking of tuple unpacking of a returned tuple, which is indeed useful ... but multiple values are something different. (Languages which support that include Common Lisp.) Multiple values has been proposed for Python, but never implemented.

Arguments are not passed "by value". They are passed "by reference". If arguments were passed by value, a function passed an array as an argument would not be able to modify it and have that modification affect the calling context, e.g.:

>>> def foo(ary):
... ary.append("yermom")
...
>>> a = ["monkey"]
>>> foo(a)
>>> a
['monkey', 'yermom']

0 Comments:

Post a Comment

<< Home