= Introduction to Python = The metabolic modelling software we will be using, {{{ScrumPy}}}, is written in {{{Python}}}. {{{Python}}} is a high-level, object-oriented, interpreted programming language, it has a large standard library, and supports multiple programming paradigms. It is also syntactically clear and easy to learn. This is a very brief introduction to some of the basic features of the language, for a more complete introduction to the topic, see Lutz & Ascher, "Learning Python" O'Reilly Media inc. (Edition 2 or greater). A good source of {{{Python}}} documentation can be found [[http://docs.python.org/ | here]]. == Getting started == We will be using {{{Python}}} from the {{{ScrumPy}}} environment. To start a new {{{ScrumPy}}} session open a terminal and type "{{{ScrumPy}}}": {{{ user@machine:~$ ScrumPy & }}} which will launch the {{{ScrumPy}}} window. == Data types == === Numbers === The numerical types we will be dealing with are integers, {{{int}}}, and floating-point numbers, {{{float}}}. Integers are written as a sequence of digits. Floats are written as digits with a decimal point in the sequence, and an optional exponent ({{{e}}} or {{{E}}}). {{{#!python >>> n_int = 135 >>> n_int 135 >>> n_float = 10e-10 >>> n_float 1.0000e-9 }}} The type of a given data object can be checked using the built-in function {{{type()}}}. {{{#!python >>> type(n_int) >>>type(n_float) }}} Floats and integers can be interconverted using the constructors {{{int()}}} or {{{float()}}}. {{{#!python >>> n_int2float=float(n_int) >>> n_int2float 135.0 >>> type(n_int2float) #n_int is still an integer }}} The common mathematical operators ({{{+,-,/,*}}}) work as expected, note that {{{x**y}}} means ''x''^y^. === Boolean === Booleans are a subtype of integers. A boolean type is either {{{True}}} or {{{False}}}, and can be very useful when writing conditional statements, i.e. {{{if something is True, do something}}}. Also, the integer {{{0}}} is {{{False}}}. {{{#!python >>> val=True >>> if val: print 'val is true' 'val is true' >>> val=False >>> if val: print 'val is true' >>> }}} === Strings === Strings are collections of characters. Characters in a string can be accessed by ''indexing'', and ''membership'' of a subset of characters in a string can be evaluated. {{{#!python >>> s_1 = 'another string' #create string >>> s_2 = s_1[:7] #create new string of characters 0 to 7 in s_1 >>> s_2 'another' >>> if s_2 in s_1: #check for membership of s_2 in s_1 print 'true' true >>> type(s_1) >>> str(n_int) '135' }}} == Lists (and tuples) == Lists and tuples are collections of items. The main difference between the two is that tuples are ''immutable'' - once a tuple is created it cannot be changed, whereas lists can. For these exercises we will mainly use lists. An empty list can be created by assigning a pair of closed square brackets to a variable. {{{#!python >>> empty_list=[] }}} Items can be appended to a list by using the ''append()'' method. {{{#!python >>> empty_list.append('string 1') >>> empty_list ['string 1'] }}} A list can also be created and populated in one go. {{{#!python >>> empty_list=['string 1'] >>> empty_list ['string 1'] }}} Items can be removed from a list using the ''remove()'' method. {{{#!python >>> empty_list.remove('string 1') >>> empty_list [] }}} As with strings, indexing can be used to copy a subset of a list, keep in mind that the indices of items in lists (like characters in strings) are numbered from 0. Membership of an item in a list can be evaluated as described for strings. The index of a known item can be retrieved using the ''index()'' method. {{{#!python >>> empty_list.index('string_1') 0 }}} == Dictionaries == In other programming languages dictionaries are sometimes called "associative arrays". Unlike lists, dictionaries store collections of items that are ordered by keys, not indices. There is no specific order of the items in a dictionary. The keys of a dictionary must be unique (for a given dictionary) and be ''hashable'', for now this means that any object that is not a list can be used as a key. Here are some examples of dictionaries in action: {{{#!python >>> dict_1 = {'alfa':1,'beta':2} #create a dictionary >>> keys = ['alfa','beta'] >>> vals = [1,2] >>> dict_1 = dict(zip(keys,vals)) #create a dictionary from two lists >>> dict_1 {'alfa':1,'beta':2} >>> dict_1['alfa'] #access value '1' by key 'alfa' 1 >>> dict_1.has_key('beta') #check that dict_1 has key 'beta' True >>> dict_1.keys() #print keys of dict_1 ['alfa','beta'] >>> dict_1.values() #print values [1,2] }}} == Modules and functions == {{{Python}}} can be used in interactive mode (as we have seen above), as well as in batch mode. A pice of {{{Python}}} code can be saved in a text file with the file extension {{{.py}}} (in {{{ScrumPy}}} the most convenient option is the build-in IDLE text editor, accessed from the tool-bar under {{{File> New window}}}). The module can be run in the {{{ScrumPy}}} shell by ''importing'' the file. Assuming we have saved a file names ''some_py.py'' in the current directory, this is how it works: {{{ user@machine:~$ ls *.py #in terminal, list all .py files some_py.py user@machine:~$ more some_py.py #Python 'Hello world!' program print 'Hello world!' }}} {{{#!python >>> import some_py #import some_py.py (note absence of extension!) Hello world! }}} It is usually more convenient to structure the stored code into functions that can be executed from the imported module. Functions are defined using the key-word ''def''. {{{ user@machine:~$ more some_py_func.py #Python 'Hello world!' program, accessed by function def print_hello(): print 'Hello world!' }}} {{{#!python >>> import some_py_func >>> some_py_func.print_hello() Hello world! >>> def print_hello(): #functions can also be defined in the shell print 'Hello world!' >>> print_hello() Hello world! }}} Functions often require ''arguments'' that the user is supposed to provide. {{{ user@machine:~$ more some_py_func.py #print user-specified string def print_string(string): print string }}} {{{#!python >>> reload(some_py_func) #if an imported module is modified the changes are updated by reloading the module >>> some_py_func.print_string('Hello world!') Hello world! }}} In many applications functions return objects to the user. {{{ user@machine:~$ more some_py_func.py #return list of characters in user-specified string def print_string(string): return list(string) }}} {{{#!python >>> reload(some_py_func) >>> hello_list = some_py_func.print_string('Hello world!') >>> hello_list ['H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!'] }}} == Objects == As mentioned, {{{Python}}} supports multiple programming paradigm, one of those being object-orientation. Object-orientation allows collection of data into ''objects'', or class ''instances''. The data collected in objectes is referred to as ''fields'' or ''attributes'', objects also store functions that usually performs actions on the attributes. Object-specific functions are called ''methods''. Here is a small example of class definition, initialisation, and usage of a class that stores a list and a dictionary. {{{ user@machine:~$ more StringDL.py class StringDnLs: def __init__(self): self.str_list=[] self.str_dict={} def add2List(self,item): str_list.append(item) def add2Dict(self,key,val): str_dict[key]=val }}} {{{#!python >>> import StringDL #import module >>> strdn = StringDL.StringDnLs() #create instance of class StringDnLs >>> strdn.str_list #print StringDnLs field str_list [] # which is empty >>> strdn.addList('a string') # add a string to str_list using method addList(item) >>> strdn.str_list ['a string'] }}} == Loops, conditionals, assignment, evaluation, and others == Some of the conventions for {{{Python}}} syntax we have already seen. Useful built-in functions include {{{len()}}}, which returns the length of an object, {{{#!python >>> a_list = ['a','b','c'] >>> len(a_list) 3 }}} and {{{dir()}}}, which returns a list of methods and attributes of an object. {{{#!python >>> dir(strdn) #strdn - as defined under Objects ['__doc__', '__init__', '__module__', 'add2Dict', 'add2List', 'str_dict', 'str_list'] }}} The {{{for}}} loop is used to iterate over an iterable object, e.g. a list. Depending on how the loop is formulated the loop variable will either be an item in the iterable object or an index. {{{#!python >>> a_list = ['a','b','c'] >>> for item in a_list: #iterating over the items print item a b c >>> for i in range(len(a_list)): #iterating over indices print a_list[i] a b c }}} {{{while}}} loops iterate until a condition is fulfilled. {{{#!python >>> a_list = ['a','b','c'] >>> i = 0 #assign value 0 to variable i >>> while i>> a_list = ['a',1,'c',2] >>> for item in a_list: if type(item)==type(str()): #check if item is of string type print item+' is string' else: #if not... print str(item)+' is not string' 'a is string' '1 is not string' 'c is string' '2 is not string' }}} If several options are possible the {{{elif}}} statement can be used. {{{#!python >>> for item in a_list: if type(item)==type(str()): print item+' is string' elif type(item)==type(int()): print str(item)+' is int' else: print str(item)+' is unkown' 'a is string' '1 is int' 'c is string' '2 is int' }}} You may have noticed it already, but it is necessary to point out the distinction between assignment and evaluation: {{{#!python >>> a = 'string' #assignment >>> a=='string' #evaluation, is a equal to 'string'? True >>> a!='string' #evaluation, is a not equal to 'string'? False }}}