# HG changeset patch # User Santosh G. Vattam # Date 1253269448 -19800 # Node ID 7f22e5b9a2d9b229e6b40fd1a1e40f7d5379aeab # Parent 780effcd7c5af94052bdf65b3988e1640373488f# Parent 5e3ce06069cf94d1b6b9345472fad4140088055f Merged branches Puneeth and Vattam. diff -r 780effcd7c5a -r 7f22e5b9a2d9 basic_python/intro.rst --- a/basic_python/intro.rst Fri Sep 18 15:49:06 2009 +0530 +++ b/basic_python/intro.rst Fri Sep 18 15:54:08 2009 +0530 @@ -543,7 +543,8 @@ False The **while** loop -~~~~~~~~~~~~~~~~~~ +================== + The Python **while** loop is similar to the C/C++ while loop. The syntax is as follows: @@ -572,7 +573,7 @@ 5 The **if** conditional -~~~~~~~~~~~~~~~~~~~~~~ +====================== The Python **if** block provides the conditional execution of statements. If the condition evaluates as true the block of statements defined under the if @@ -612,7 +613,7 @@ print n, " is 0" **raw_input()** -~~~~~~~~~~~~~~~ +=============== In the previous example we saw the call to the raw_input() subroutine. The **raw_input()** method is used to take user inputs through the console. @@ -685,7 +686,7 @@ cannot be performed on it. Hence the exception is raised. **int()** method -~~~~~~~~~~~~~~~~ +================ Generally for computing purposes, the data used is not strings or raw data but on integers, floats and similar mathematical data structures. The data obtained @@ -713,268 +714,3 @@ 'Guido Van Rossum' >>> numvar = int(stringvar) - -Functions in Python: **def** -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -*Functions* allow us to enclose a set of statements and call the function again -and again instead of repeating the group of statements everytime. Functions also -allow us to isolate a piece of code from all the other code and provides the -convenience of not polluting the global variables. - -*Function* in python is defined with the keyword **def** followed by the name -of the function, in turn followed by a pair of parenthesis which encloses the -list of parameters to the function. The definition line ends with a ':'. The -definition line is followed by the body of the function intended by one block. -The *Function* must return a value:: - - def factorial(n): - fact = 1 - for i in range(2, n): - fact *= i - - return fact - -The code snippet above defines a function with the name factorial, takes the -number for which the factorial must be computed, computes the factorial and -returns the value. - -A *Function* once defined can be used or called anywhere else in the program. We -call a fucntion with its name followed by a pair of parenthesis which encloses -the arguments to the function. - -The value that function returns can be assigned to a variable. Let's call the -above function and store the factorial in a variable:: - - fact5 = factorial(5) - -The value of fact5 will now be 120, which is the factorial of 5. Note that we -passed 5 as the argument to the function. - -It may be necessary to document what the function does, for each of the function -to help the person who reads our code to understand it better. In order to do -this Python allows the first line of the function body to be a string. This -string is called as *Documentation String* or *docstring*. *docstrings* prove -to be very handy since there are number of tools which can pull out all the -docstrings from Python functions and generate the documentation automatically -from it. *docstrings* for functions can be written as follows:: - - def factorial(n): - 'Returns the factorial for the number n.' - fact = 1 - for i in range(2, n): - fact *= i - - return fact - -An important point to note at this point is that, a function can return any -Python value or a Python object, which also includes a *Tuple*. A *Tuple* is -just a collection of values and those values themselves can be of any other -valid Python datatypes, including *Lists*, *Tuples*, *Dictionaries* among other -things. So effectively, if a function can return a tuple, it can return any -number of values through a tuple - -Let us write a small function to swap two values:: - - def swap(a, b): - return b, a - - c, d = swap(a, b) - -Function scope ---------------- -The variables used inside the function are confined to the function's scope -and doesn't pollute the variables of the same name outside the scope of the -function. Also the arguments passed to the function are passed by-value if -it is of basic Python data type:: - - def cant_change(n): - n = 10 - - n = 5 - cant_change(n) - -Upon running this code, what do you think would have happened to value of n -which was assigned 5 before the function call? If you have already tried out -that snippet on the interpreter you already know that the value of n is not -changed. This is true of any immutable types of Python like *Numbers*, *Strings* -and *Tuples*. But when you pass mutable objects like *Lists* and *Dictionaries* -the values are manipulated even outside the function:: - - >>> def can_change(n): - ... n[1] = James - ... - - >>> name = ['Mr.', 'Steve', 'Gosling'] - >>> can_change(name) - >>> name - ['Mr.', 'James', 'Gosling'] - -If nothing is returned by the function explicitly, Python takes care to return -None when the funnction is called. - -Default Arguments ------------------ - -There may be situations where we need to allow the functions to take the -arguments optionally. Python allows us to define function this way by providing -a facility called *Default Arguments*. For example, we need to write a function -that returns a list of fibonacci numbers. Since our function cannot generate an -infinite list of fibonacci numbers, we need to specify the number of elements -that the fibonacci sequence must contain. Suppose, additionally, we want to the -function to return 10 numbers in the sequence if no option is specified we can -define the function as follows:: - - def fib(n=10): - fib_list = [0, 1] - for i in range(n - 2): - next = fib_list[-2] + fib_list[-1] - fib_list.append(next) - return fib_list - -When we call this function, we can optionally specify the value for the -parameter n, during the call as an argument. Calling with no argument and -argument with n=5 returns the following fibonacci sequences:: - - fib() - [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] - fib(5) - [0, 1, 1, 2, 3] - -Keyword Arguments ------------------ - -When a function takes a large number of arguments, it may be difficult to -remember the order of the parameters in the function definition or it may -be necessary to pass values to only certain parameters since others take -the default value. In either of these cases, Python provides the facility -of passing arguments by specifying the name of the parameter as defined in -the function definition. This is known as *Keyword Arguments*. - -In a function call, *Keyword arguments* can be used for each argument, in the -following fashion:: - - argument_name=argument_value - Also denoted as: keyword=argument - - def wish(name='World', greetings='Hello'): - print "%s, %s!" % (greetings, name) - -This function can be called in one of the following ways. It is important to -note that no restriction is imposed in the order in which *Keyword arguments* -can be specified. Also note, that we have combined *Keyword arguments* with -*Default arguments* in this example, however it is not necessary:: - - wish(name='Guido', greetings='Hey') - wish(greetings='Hey', name='Guido') - -Calling functions by specifying arguments in the order of parameters specified -in the function definition is called as *Positional arguments*, as opposed to -*Keyword arguments*. It is possible to use both *Positional arguments* and -*Keyword arguments* in a single function call. But Python doesn't allow us to -bungle up both of them. The arguments to the function, in the call, must always -start with *Positional arguments* which is in turn followed by *Keyword -arguments*:: - - def my_func(x, y, z, u, v, w): - # initialize variables. - ... - # do some stuff - ... - # return the value - -It is valid to call the above functions in the following ways:: - - my_func(10, 20, 30, u=1.0, v=2.0, w=3.0) - my_func(10, 20, 30, 1.0, 2.0, w=3.0) - my_func(10, 20, z=30, u=1.0, v=2.0, w=3.0) - my_func(x=10, y=20, z=30, u=1.0, v=2.0, w=3.0) - -Following lists some of the invalid calls:: - - my_func(10, 20, z=30, 1.0, 2.0, 3.0) - my_func(x=10, 20, z=30, 1.0, 2.0, 3.0) - my_func(x=10, y=20, z=30, u=1.0, v=2.0, 3.0) - -Parameter Packing and Unpacking -------------------------------- - -The positional arguments passed to a function can be collected in a tuple -parameter and keyword arguments can be collected in a dictionary. Since keyword -arguments must always be the last set of arguments passed to a function, the -keyword dictionary parameter must be the last parameter. The function definition -must include a list explicit parameters, followed by tuple paramter collecting -parameter, whose name is preceded by a *****, for collecting positional -parameters, in turn followed by the dictionary collecting parameter, whose name -is preceded by a ****** :: - - def print_report(title, *args, **name): - """Structure of *args* - (age, email-id) - Structure of *name* - { - 'first': First Name - 'middle': Middle Name - 'last': Last Name - } - """ - - print "Title: %s" % (title) - print "Full name: %(first)s %(middle)s %(last)s" % name - print "Age: %d\nEmail-ID: %s" % args - -The above function can be called as. Note, the order of keyword parameters can -be interchanged:: - - >>> print_report('Employee Report', 29, 'johny@example.com', first='Johny', - last='Charles', middle='Douglas') - Title: Employee Report - Full name: Johny Douglas Charles - Age: 29 - Email-ID: johny@example.com - -The reverse of this can also be achieved by using a very identical syntax while -calling the function. A tuple or a dictionary can be passed as arguments in -place of a list of *Positional arguments* or *Keyword arguments* respectively -using ***** or ****** :: - - def print_report(title, age, email, first, middle, last): - print "Title: %s" % (title) - print "Full name: %s %s %s" % (first, middle, last) - print "Age: %d\nEmail-ID: %s" % (age, email) - - >>> args = (29, 'johny@example.com') - >>> name = { - 'first': 'Johny', - 'middle': 'Charles', - 'last': 'Douglas' - } - >>> print_report('Employee Report', *args, **name) - Title: Employee Report - Full name: Johny Charles Douglas - Age: 29 - Email-ID: johny@example.com - -Nested Functions and Scopes ---------------------------- - -Python allows nesting one function inside another. This style of programming -turns out to be extremely flexible and powerful features when we use *Python -decorators*. We will not talk about decorators is beyond the scope of this -course. If you are interested in knowing more about *decorator programming* in -Python you are suggested to read: - -| http://avinashv.net/2008/04/python-decorators-syntactic-sugar/ -| http://personalpages.tds.net/~kent37/kk/00001.html - -However, the following is an example for nested functions in Python:: - - def outer(): - print "Outer..." - def inner(): - print "Inner..." - print "Outer..." - inner() - - >>> outer() - diff -r 780effcd7c5a -r 7f22e5b9a2d9 basic_python/strings_dicts.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/basic_python/strings_dicts.rst Fri Sep 18 15:54:08 2009 +0530 @@ -0,0 +1,336 @@ +======= +Strings +======= + +Strings were briefly introduced previously in the introduction document. In this +section strings will be presented in greater detail. All the standard operations +that can be performed on sequences such as indexing, slicing, multiplication, length +minimum and maximum can be performed on string variables as well. One thing to +be noted is that strings are immutable, which means that string variables are +unchangeable. Hence, all item and slice assignments on strings are illegal. +Let us look at a few example. + +:: + + >>> name = 'PythonFreak' + >>> print name[3] + h + >>> print name[-1] + k + >>> print name[6:] + Freak + >>> name[6:0] = 'Maniac' + Traceback (most recent call last): + File "", line 1, in + TypeError: 'str' object does not support item assignment + +This is quite expected, since string objects are immutable as already mentioned. +The error message is clear in mentioning that 'str' object does not support item +assignment. + +String Formatting +================= + +String formatting can be performed using the string formatting operator represented +as the percent (%) sign. The string placed before the % sign is formatted with +the value placed to the right of it. Let us look at a simple example. + +:: + + >>> format = 'Hello %s, from PythonFreak' + >>> str1 = 'world!' + >>> print format % str1 + Hello world!, from PythonFreak + +The %s parts of the format string are called the coversion specifiers. The coversion +specifiers mark the places where the formatting has to be performed in a string. +In the example the %s is replaced by the value of str1. More than one value can +also be formatted at a time by specifying the values to be formatted using tuples +and dictionaries (explained in later sections). Let us look at an example. + +:: + + >>> format = 'Hello %s, from %s' + >>> values = ('world!', 'PythonFreak') + >>> print format % values + Hello world!, from PythonFreak + +In this example it can be observed that the format string contains two conversion +specifiers and they are formatted using the tuple of values as shown. + +The s in %s specifies that the value to be replaced is of type string. Values of +other types can be specified as well such as integers and floats. Integers are +specified as %d and floats as %f. The precision with which the integer or the +float values are to be represented can also be specified using a **.** (**dot**) +followed by the precision value. + +String Methods +============== + +Similar to list methods, strings also have a rich set of methods to perform various +operations on strings. Some of the most important and popular ones are presented +in this section. + +**find** +~~~~~~~~ + +The **find** method is used to search for a substring within a given string. It +returns the left most index of the first occurence of the substring. If the +substring is not found in the string then it returns -1. Let us look at a few +examples. + +:: + + >>> longstring = 'Hello world!, from PythonFreak' + >>> longstring.find('Python') + 19 + >>> longstring.find('Perl') + -1 + +**join** +~~~~~~~~ + +The **join** method is used to join the elements of a sequence. The sequence +elements that are to be join ed should all be strings. Let us look at a few +examples. + +:: + + >>> seq = ['With', 'great', 'power', 'comes', 'great', 'responsibility'] + >>> sep = ' ' + >>> sep.join(seq) + 'With great power comes great responsibility' + >>> sep = ',!' + >>> sep.join(seq) + 'With,!great,!power,!comes,!great,!responsibility' + +*Try this yourself* + +:: + + >>> seq = [12,34,56,78] + >>> sep.join(seq) + +**lower** +~~~~~~~~~ + +The **lower** method, as the name indicates, converts the entire text of a string +to lower case. It is specially useful in cases where the programmers deal with case +insensitive data. Let us look at a few examples. + +:: + + >>> sometext = 'Hello world!, from PythonFreak' + >>> sometext.lower() + 'hello world!, from pythonfreak' + +**replace** +~~~~~~~~~~~ + +The **replace** method replaces a substring with another substring within +a given string and returns the new string. Let us look at an example. + +:: + + >>> sometext = 'Concise, precise and criticise is some of the words that end with ise' + >>> sometext.replace('is', 'are') + 'Concaree, precaree and criticaree are some of the words that end with aree' + +Observe here that all the occurences of the substring *is* have been replaced, +even the *is* in *concise*, *precise* and *criticise* have been replaced. + +**split** +~~~~~~~~~ + +The **split** is one of the very important string methods. split is the opposite of the +**join** method. It is used to split a string based on the argument passed as the +delimiter. It returns a list of strings. By default when no argument is passed it +splits with *space* (' ') as the delimiter. Let us look at an example. + +:: + + >>> grocerylist = 'butter, cucumber, beer(a grocery item??), wheatbread' + >>> grocerylist.split(',') + ['butter', ' cucumber', ' beer(a grocery item??)', ' wheatbread'] + >>> grocerylist.split() + ['butter,', 'cucumber,', 'beer(a', 'grocery', 'item??),', 'wheatbread'] + +Observe here that in the second case when the delimiter argument was not set +**split** was done with *space* as the delimiter. + +**strip** +~~~~~~~~~ + +The **strip** method is used to remove or **strip** off any whitespaces that exist +to the left and right of a string, but not the whitespaces within a string. Let +us look at an example. + +:: + + >>> spacedtext = " Where's the text?? " + >>> spacedtext.strip() + "Where's the text??" + +Observe that the whitespaces between the words have not been removed. + +:: + + Note: Very important thing to note is that all the methods shown above do not + transform the source string. The source string still remains the same. + Remember that **strings are immutable**. + + +I/O: Reading and Writing Files +============================== + +Files are very important aspects when it comes to computing and programming. +Up until now the focus has been on small programs that interacted with users +through **input()** and **raw_input()**. Generally, for computational purposes +it becomes necessary to handle files, which are usually large in size as well. +This section focuses on basics of file handling. + +Opening Files +~~~~~~~~~~~~~ + +Files can be opened using the **open()** method. **open()** accepts 3 arguments +out of which 2 are optional. Let us look at the syntax of **open()**: + +*f = open( filename, mode, buffering)* + +The *filename* is a compulsory argument while the *mode* and *buffering* are +optional. The *filename* should be a string and it should be the complete path +to the file to be opened (The path can be absolute or relative). Let us look at +an example. + +:: + + >>> f = open ('basic_python/interim_assessment.rst') + +The *mode* argument specifies the mode in which the file has to be opened. +The following are the valid mode arguments: + +**r** - Read mode +**w** - Write mode +**a** - Append mode +**b** - Binary mode +**+** - Read/Write mode + +The read mode opens the file as a read-only document. The write mode opens the +file in the Write only mode. In the write mode, if the file existed prior to the +opening, the previous contents of the file are erased. The append mode opens the +file in the write mode but the previous contents of the file are not erased and +the current data is appended onto the file. +The binary and the read/write modes are special in the sense that they are added +onto other modes. The read/write mode opens the file in the reading and writing +mode combined. The binary mode can be used to open a files that do not contain +text. Binary files such as images should be opened in the binary mode. Let us look +at a few examples. + +:: + + >>> f = open ('basic_python/interim_assessment.rst', 'r') + >>> f = open ('armstrong.py', 'r+') + +The third argument to the **open()** method is the *buffering* argument. This takes +a boolean value, *True* or *1* indicates that buffering has to be enabled on the file, +that is the file is loaded on to the main memory and the changes made to the file are +not immediately written to the disk. If the *buffering* argument is *0* or *False* the +changes are directly written on to the disk immediately. + +Reading and Writing files +~~~~~~~~~~~~~~~~~~~~~~~~~ + +**write()** +----------- + +**write()**, evidently, is used to write data onto a file. It takes the data to +be written as the argument. The data can be a string, an integer, a float or any +other datatype. In order to be able to write data onto a file, the file has to +be opened in one of **w**, **a** or **+** modes. + +**read()** +---------- + +**read()** is used to read data from a file. It takes the number of bytes of data +to be read as the argument. If nothing is specified by default it reads the entire +contents from the current position to the end of file. + +Let us look at a few examples: + +:: + + >>> f = open ('randomtextfile', 'w') + >>> f.write('Hello all, this is PythonFreak. This is a random text file.') + >>> f = open ('../randomtextfile', 'r') + >>> f = open ('../randomtextfile', 'r') + >>> f.read(5) + 'Hello' + >>> f.read() + ' all, this is PythonFreak. This is a random text file.' + >>> f.close() + +**readline()** +-------------- + +**readline()** is used to read a file line by line. **readline()** reads a line +of a file at a time. When an argument is passed to **readline()** it reads that +many bytes from the current line. + +One other method to read a file line by line is using the **read()** and the +**for** construct. Let us look at this block of code as an example. + +:: + + >>> f = open('../randomtextfile', 'r') + >>> for line in f: + ... print line + ... + Hello all! + + This is PythonFreak on the second line. + + This is a random text file on line 3 + +**close()** +----------- + +One must always close all the files that have been opened. Although, files opened +will be closed automatically when the program ends. When files opened in read mode +are not closed it might lead to uselessly locked sometimes. In case of files +opened in the write mode it is more important to close the files. This is because, +Python maybe using the file in the buffering mode and when the file is not closed +the buffer maybe lost completely and the changes made to the file are lost forever. + + +Dictionaries +============ + +A dictionary in general, are designed to be able to look up meanings of words. +Similarly, the Python dictionaries are also designed to look up for a specific +key and retrieve the corresponding value. Dictionaries are data structures that +provide key-value mappings. Dictionaries are similar to lists except that instead +of the values having integer indexes, dictionaries have keys or strings as indexes. +Let us look at an example of how to define dictionaries. + +:: + + >>> dct = { 'Sachin': 'Tendulkar', 'Rahul': 'Dravid', 'Anil': 'Kumble'} + +The dictionary consists of pairs of strings, which are called *keys* and their +corresponding *values* separated by *:* and each of these *key-value* pairs are +comma(',') separated and the entire structure wrapped in a pair curly braces *{}*. + +**dict()** +~~~~~~~~~~ + +The **dict()** function is used to create dictionaries from other mappings or other +dictionaries. Let us look at an example. + +:: + + >>> diction = dict(mat = 133, avg = 52.53) + +**String Formatting with Dictionaries:** + +String formatting was discussed in the previous section and it was mentioned that +dictionaries can also be used for formatting more than one value like . \ No newline at end of file