Wednesday, October 5, 2011

LPTHW - Exercise 52

This is the last exercise in the LPTHW book. In this exercise we will create a web based game engine for the Gothon game (the one we created in exercise 42), using the structure we created in exercise 47, along with tests and everything.

The first thing I did was to copy the entire contents of ex47 to ex52. Then I renamed game.py to map.py and made a corresponding change for the test case also. Then I ran 'nosetests' and everything seems to be fine at this stage.

In exercise 42, each room was a function in the Room class. But now in exercise 52, we will make each Room an instance of the Room class. I coded the class map.py (containing all the rooms) as shown in the book. Next, I am going to copy the map_tests.py file as is in the tests directory.

After copying the code in map.py, I created another Python module for messages, called messages.py. This module will contain the initial text for all the rooms, as well as the transition text, which is displayed to the user when they transition from one room to another.

Next, I refactored map_tests.py to test all the rooms, their initial text, and transitions.

The book then explains how lpthw.web maintains sessions. I understand how sessions are managed, but the session variable which seems global to the module confused me, because it makes me think that only one instance of that variable would exist.

I copied the apps.py file in bin, and also fixed a couple of bugs.

I also added two HTML templates - layout.html, show_room.html, and game_lost.html

Part of the code is embedded below:

LPTHW - Exercise 51

In this exercise, we learn how to deal with form input and a bit about testing web apps.

The first thing I did was to change app.py and refactor it to handle web input. We will handle simple input as GET input parameters to start with.

Here is the new app.py file:



Now if you notice, in this file we use the line

form = web.input(name="Nobody")

to handle the input. If the input contains a 'name' parameter, then we will use it, else it will default to "Nobody", since we have given a default value as an argument to the function call.

Getting the values as url parameters is not a good idea:

This is a good beginning, but we should really be getting the values in a form and not as command line parameters. For this we will need to add some HTML and a method in the Index class to handle POST data (since this is the default method for sending form data).

I made a few changes to app.py, index.html, and added a new file hello_form.html All the code is embedded below:



Don't repeat boilerplate code:

It's very good that we can now handle form data. However, the observant programmer must have noticed that both index.html, and hello_form.html have common boilerplate code. It would be good if we can remove the repetition. Well, we can, if we use templates.


All the code which uses templates is embedded below:

LPTHW - Exercise 50

In this exercise we will make a web application from the Gothons game, which we made in exercise 46. To simplify the process of making a web application, we need a we need a web framework. For this exercise we will use lpthw.web, which is the same as the webpy framework.

I installed the web framework thus
pip install lpthw.web

Then I created a project for the web application by creating a directory in my projects directory:
ex50
/bin
app.py
/docs
/gothonweb
__init__.py
/templates
__init__.py
/tests

I just copied the code provided in LPTHW in app.py

I ran the webserver with 'python bin/app.py' and successfully loaded the url http://localhost:8080

However, I realized that lpthw.web was not installed in my virtualenv as I would have expected it to be. It was actually installed in /usr/local/lib/python2.6/dist-packages/ This seems strange and incorrect to me. I am not quite sure what went wrong, so I asked a question on StackOverflow.

The code for this exercise is embedded below:

Tuesday, October 4, 2011

LPTHW - Exercise 49

In the previous exercise, we had created a scanner, which would take a line of words as input and return to us a list of tuples which gave us the type of each word.

In this exercise, we try and add some intelligence to our game, and identify sentence parts in the user input.

This is a bit of an over-simplification, but we will consider a sentence to consist of the following structure: subject verb object

If our sentence contains words from our lexicon and is of the above form, then we will be able to parse the sentence and take an action in the game based on it. We ignore stop words, and also allow for arbitrary upper/lower case. This gives the player a decent amount of freedom in creating their commands. So for example they could enter "eat bear", or they could also enter "Eat the bear" and both the inputs will be accepted as valid by the sentence parser.

For this exercise I copied the code from ex48 because we still need the lexicon and lexicon_tests files. In addition I added the files sentence.py and sentence_tests.py

The entire code is embedded below.

LPTHW - Exercise 48

In this exercise, we created an intelligent input scanner, which we can use in our games. This scanner takes a line of input, and returns a list of tuples, each containg the 'type of word' and the word itself.

We were given the unit tests (lexicon_tests.py), and were supposed to write the actual code (lexicon.py) to fulfill the tests. This exercise was a lot of fun.

The test suite and code is embedded below:

Monday, October 3, 2011

LPTHW - Exercise 47

In this exercise we create a very simple class for a game, and then create unit tests for it.

Since, I have already done much programming (albeit in Java), I am familiar with the concept of unit testing, and why it is important.

Python seems to have something called 'nose' which is a test harness similar to JUnit for Java. Here is the production and test code modules.



In our project, we have a directory called tests, which holds all our tests. The test module name is 'actualmodule_test.py', where 'actualmodule' is the name of the module which is being tested.

The test script has setup and teardown functions, but when I ran the tests with nosetests, these functions were not run. I need to figure out why.

Creating and installing a script in my distribution module

In the previous blog post, I explained how to create and distribute a package distribution. If the package were a library, then most likely this is where it would end. However, since I have created something which will be used as a command line desktop application, it would be wonderful if I could bundle a script which the user can invoke from the command line.

First I made a shell script, which would invoke a Python module, however I ran into an issue where the interpreter could not locate the Python module. I think it should have since the package has already been installed with distutils. I need to spend some time understanding how the interpreter locates modules.

In the spirit of moving ahead, I decided to create a Python script and make it executable instead. Once I created the script, I again ran setup.py, which caused this script to be copied in the 'bin' directory of my ENV. Here is the simple Python script I created.




Creating a simple distribution module

To understand better all the things I learned in Exercise 46, I am now going to create a simple distribution module which will work with distutils. Here is the documentation of how to create such a module with distutils.

I am creating a simple Python Pomodoro.

First, I copied the skeleton directory into another directory called 'pypomodoro'. Next I renamed the package directory 'NAME' to 'pypomodoro'. Next, in the tests directory, I renamed NAME_tests.py to pypomodoro_tests.py. Next, in setup.py I added 'pypomodoro' to the packages names parameter.

Packaging is usually a nightmare on all platforms... and it is not exception with Python, at least when learning it.

Anyways, here are some notes which I am hoping will help me understand all this better.

In Python project names usually use camel case. So I have renamed my python-pomodoro project to PyPomodoro.

The project directory will usually contain a few more directories and files.
PythonProject
\bin
\docs
\tests
__init__.py
module_name_tests.py
\main_project_module
__init__.py
module1.py
module2.py
setup.py

I realized that we refer to the terminology module for individual python files, as well as to directories. Directories which are modules however, must have a file called __init__.py

So, this is a bit confusing. A bit of Googling takes me to this tutorial on Python packages. This tutorial states
"Packages are a way of structuring Python's module namespace by using dotted module names"
This makes sense. Looks similar to packages in Java, but the term 'packages' in Python seems to be overloaded. I believe I also encountered it in the context of the thing which contains setup.py. Perhaps this is not a package, but a 'package distribution'.

We can import sub-modules like this:
import A.B
where we expect B to be a submodule of A. Note that B cannot be a function or a member inside A. It has to be a submodule. What this means is that the directory A, must have a file called __init__.py and also if B is a directory, it must have a file called __init__.py However, if B can also be a file. The __init__.py file is invoked when the module containing it is loaded. Here is a tutorial explaining the usage of __init__.py

Question: What if the module is loaded multiple times? Perhaps I should also ask the question, if a module CAN be loaded multiple times.



Ways to install a Python package

After doing exercise 46 of LPTHW, I realized that there are multiple ways of installing a Python package.

Here are three ways that I know of.

pip install package_name

easy_install package_name

Download and unzip the tar file and then do
python setup.py install

LPTHW Exercise 46

In this exercise, we create a skeleton directory for future Python projects. This skeleton basically contains a directory structure, and an install script.

For all this to work properly, we need to have certain Python packages installed. The book recommends the following packages.

pip
distribute
nose
virtialenv

Now I am going to install all of the above packages.

Installing Pip:
pip is a Python package installer (which installs packages from the Python package index). It is meant to be a replacement for easy_install. So anything which can be installed with easy_install can also be installed with pip.

The pre-requisites for installing Pip are either setup_tools, or distribute. I read that setup_tools is not supported on Python 3.0. Even though this is not a problem, since I have Python 2.6, I figured it would be a good idea to go with 'distribute'

Distribute is also on the list of packages to install, so I install 'distribute' first.
curl http://python-distribute.org/distribute_setup.py | python

But I am also a bit curious about what distribute does. The documentation says it is a tool to 'Easily download, build, install, upgrade, and uninstall Python packages'. So basically this looks like a lower level tool which is needed by pip.

Now that I have installed 'distribute' I also installed Pip.

Installing VirtualEnv
Next I installed 'virtualenv' using pip:
'sudo pip install virtualenv'

I think there is a lot to virtualenv. I will write more about it in my next blog post. For now, I will link to the official virtualenv documentation page.

After installing virtualenv, I created an environment called ENV1.

I will now try to install nose in ENV1.

I activated the newly created environment running source bin/activate and then ran pip install nose.

Extra Credit:

So what do all of these software's do ?

  1. pip - Is used for installing packages which are present in the PyPy package index
  2. Distribute - Is a lower level tool for building, installing, and managing Python packages
  3. VirtualEnv - Is a tool to create isolated environments for Python
  4. Nose - Extends unittest to make testing easier
Understand setup.py

setup.py is used by the Python distutils as a standard way for installing third party Python modules. Before distutils, module creators would have to create install files for all the different platforms. Off course this is not easy, and I am sure there would be times when some module creators would not create such files. I believe since distutils uses Python, it is a way to use Python to install modules, rather than relying on the platforms way of installing Python packages. I also think this is good encapsulation :-)

If you are using distutils then you will know immediately if the package maintainer has packages their application in standard way or not. A Python package which is meant to be installed using distutils will always have a setup.py file bundled with it. This file will contain the calls it makes to distutils to install the package.

When we run
python setup.py install
There are really two things that happen. First is the build step, which puts all the files which need to be copied into the distribution root's build directory. I think by distribution root they mean the directory which is created for the distributed package. We can however change the directory in which the build process happens, if we so desire.

Once the build phase has completed, the install phase will copy the files to the chosen install directory. If no directory is specified then the default directory, which on *nix systems is usually /something/pythonX.x/site-packages. On my Ubuntu system it is /usr/local/lib/python2.6/site-packages However, it seems that modules are actually being installed in dist-packages.

It is possible to install the package using an alternate install scheme. There are various alternate install schemes. Even though I have not looked into them in any great detail, they seem to be able to not only customize the install location, but also determine who is able to access and use the package. Details for all of these install schemes is available here.

I will stop here as far as using disutils is concerned. This is a good introduction, and should be fine to start with.

Now I will understand the basics of using distutils for package creators.

Since distutils is also about packaging, let us try to understand some basic terminology. We will talk about general Python terminology followed by distutils terminology.

  1. Module - This is the basic unit of code-reusability in Python. It is a block of code, which is usually imported by other code to be used. This is usually a single Python file.
  2. Package - This is usually a module that contains other modules. It is usually contained in a directory. This directory must always contain a file called __init__.py
  3. Root Package - This is the root of the heirarchies of packages. The root package usually contains the entire Python standard library, along with many stand alone modules which do not belong anywhere else. Now the documentation says something which totally freaked me out ... "Unlike regular packages, modules in the root package can be found in many directories: in fact, every directory listed in sys.pathcontributes modules to the root package"
distutils specific terminology:

  1. Module Distribution is a collection of Python modules and packages, which are meant to be distributed en-masse.
  2. Distribution Root is the directory which contains setup.py

Now let us understand the setup script from the perspective of a package creator. The main purpose of a setup script is to describe your module to distutils, so that the various commands that operate on your module do the right thing.

Without getting into too much detail, I will now create a simple module distribution and create a setup script for it. I will write about it in a separate blog post.

Saturday, October 1, 2011

LPTHW Exercise 45

In this exercise we learn about IS-A and HAS-A relationships. We also learn how to invoke A superclass constructor from a subclass.

Friday, September 30, 2011

LPTHW Exercise 44

In this exercise we take the code written in exercise 43 and comment it.

There is still plenty of scope for improvement, such as proper super class and subclass relationships between individual rooms and a proposed Room superclass.

Here's the code.

LPTHW Exercise 43

In this exercise I have made a game. The program is not perfect, but it works well. I still need to refactor it for the following:

1. Use proper class..subclass relationships. For example SpacedRepitition should be a subclass of another class called Room

2. Add proper documentation

3. Use proper coding standards

I will address most of these issues in the next exercise

Thursday, September 29, 2011

LPTHW Exercise 42

In this exercise we re-create the Gothons game with classes instead of "functions and maps"

The getattr function is used to obtain an attribute from an object using a String to identify the needed attribute. Ref [1]

Wednesday, September 28, 2011

LPTHW Exercise 41

Gosh, I honestly could not type this in. Copy paste...

LPTHW Exercise 40

In this exercise we learn about Maps. They are also called 'dictionary' in Python. An interesting thing we do in this exercise is putting a function in the map.

LPTHW Exercise 39

In this exercise we do some stuff with lists...




Tuesday, September 27, 2011

LPTHW Exercise 37

Keywords

  • and - Logical AND operation
  • del- Deletes objects. These objects could be local variables, or even elements from a list. - References [1] [2]
  • from - Used for importing elements from modules
  • not - The logical NOT operation
  • while - Used for looping until the condition in while remains true
  • as - When used with the 'import' statement, the as keyword is used to rename the bound object. It can also be used with the 'with' statement... though I am not sure what that statement does.
  • elif - 'else if'
  • global - This causes a local variable to be visible outside of it's scope. Ref [1]
  • or - The logical OR operation
  • with - This seems like a more convenient alternative to try...finally when there is a setup, execution, and teardown cycle to be performed. Ref [1]
  • assert - The 'assert' statement is used to put error checking in your code. It seems to be very similar to what 'assert' does in Java
  • else - 'else' part of a conditional
  • if - Conditional
  • pass - The 'pass' statement does nothing. It is used when a statement is required syntactically, but nothing needs to be done. Ref [1]
  • yield - The yield statement causes a function to return a generator. When this generator is run, it will return a value specified by the yield statement and will do so every time it is run until the function runs out of values. This is also akin to continuations. Ref [1]. Do generators always return iterables ?
  • break - The 'break' statement breaks out of the immediately enclosing 'for' or 'while' loop. Ref [1]
  • except - The 'except' keyword is used as a counterpart to the 'try' keyword. It has a similar function to the 'catch' keyword in Java. Ref [1]
  • import - Used for importing modules and their elements
  • print - Used for printing something to the console
  • class - Used for defining a class
  • exec - Supports dynamic execution of Python code
  • in - The inclusion operator
  • raise - Raising an exception
  • continue - Continue back to the start of the loop
  • finally - The cleanup block after a try...except statement. Ref [1]
  • is - Used to determine if two values are stored in the same memory location. Ref [1]
  • return - Used to return a value from a function
  • def - Keyword used to define a function
  • for - The for loop
  • lambda - Used to create small anonymous functions. Ref [1]
  • try - Used to enclose code which could throw Exceptions. It must be followed by an 'except' statement.
Notes:
This webpage says that the 'del' keyword deletes objects. What exactly does that mean? Does it delete objects from lists, sequences, etc, or does it also delete objects from within other objects, or entire objects ?

Data Types

For data types, write out what makes up each one. For example, with strings write out how you create a string. For numbers write out a few numbers.

  • True - The boolean true value
  • False - The boolean false value
  • None - Represents nothing... looks like it is similar to the 'null' keyword in Java
  • strings - The string datatype which is a sequence of characters
  • numbers - Python supports several numeric data types
  • floats - Represents floating point numbers as per the IEEE 854-1987 standard
  • lists - An ordered collection of items

String Escapes Sequences

For string escape sequences, use them in strings to make sure they do what you think they do.

  • \\ - Result is a single backslash
  • \' - Result is the ' character
  • \" - Result is the " character
  • \a - Result is the ASCII bell
  • \b - ACSII backspace
  • \f - ASCII formfeed
  • \n - ASCII linefeed
  • \r - ASCII carriage return
  • \t - ASCII horizontal tab
  • \v - ASCII vertical tab

String Formats

Same thing for string formats: use them in some strings to know what they do.

  • %d - signed decimal
  • %i - signed integer decimal
  • %o - signed octal value
  • %u - Obsolete type now... identical to %d
  • %x - Signed hexadecimal lowercase
  • %X - Signed hexadecimal uppercase
  • %e - Floating point exponential format (lowercase)
  • %E - Floating point exponential format (uppercase)
  • %f - Floating point decimal format
  • %F - Floating point decimal format
  • %g - Floating point format. Uses lowercase format if exponent is less than -4 or not less than precision. Decimal otherwise
  • %G - Floating point format. Uses uppercase format if exponent is less than -4 or not less than precision. Decimal otherwise
  • %c - Single character. Accepts integer or single character string
  • %r - Any Python object
  • %s - String
  • %% - Results in the % character... no argument is converted

Operators

Some of these may be unfamiliar to you, but look them up anyway. Find out what they do, and if you still can't figure it out, save it for later.

  • + - addition operator
  • - - subtraction operator
  • * - multiplication operator
  • ** - The power operator. a ** b will give a to the power b
  • / - The division operator
  • // - Floor division. 9 //2 is 4
  • % - Modulus operator
  • < - Less than
  • > - Greater than
  • <= - Less than equal to
  • >= - Greater than equal to
  • == - Equality
  • != - Not equal to
  • <> - Not equal to
  • ( ) - Parenthesis for defining proper precedence
  • [ ] - Used for defining lists
  • { } - Used for defining maps ?
  • @ - Decorator
  • , - Used to separate values in a tuple
  • : - Used to delimit the key and value in map entries
  • . - Used to identify a method on a referenced object or module
  • = - Assignment operator
  • ; - Combines multiple statements into one. See [1]
  • += - Add and assign (the ones below are similar... do something and assign)
  • -=
  • *=
  • /=
  • //=
  • %=
  • **=

LPTHW Exercise 36

In this exercise I created a simple text based game. This game consists of countries and capitals. A user is flown to a country, where the immigration officer asks them the name of the capital. If you answer correctly, you get a point, if you answer incorrectly you do not get any points. The game quits when the user has correctly guessed the capitals of all the countries, or if they type CTRL-C.

Stuff I learned:
  • How to generate a random number in Python
  • How to get the length of a list
  • We can nest lists within lists
  • A function can return multiple values
  • The main function has a really strange syntax
  • The ++ increment operator is not supported in Python
  • Making a simple game is fun




LPTHW Exercise 35

In this exercise we use branches in functions.

LPTHW Exercise 34

In this exercise we learn how to get elements from a list.

animals = ['bear', 'python', 'peacock', 'kangaroo', 'whale', 'platypus']

print "The first animal is %s" % animals[0]

I did not create any Python files for this exercise. Did it in the console.

LPTHW Exercise 33

Completed exercise 33. In this exercise we learn about the while loop in Python.

LPTHW Exercise 32

In this exercise we work with lists. A list is an ordered collection of items. We can iterate through all the items in a list, using a for..in loop. A range generates a list in an arithmetic progression. We can add elements to a list using the 'append' statement.

LPTHW Exercise 31

So far we used if..elif to print different things based on some values. But in real programs, we usually use conditions to make decisions based on user input. In this exercise, we take user input and make decisions based on it.

LPTHW Exercise 30

In this exercise, we learned how to use if...elif

LPTHW Exercise 29

Completed exercise 29. This exercise covered the 'if' statement in Python.

Some learnings:
  1. The if statement does not need () after it
  2. Should end with ':'
  3. Since it is a block, it's contents should be indented
Here is the code.

LPTHW Exercise 28

In this exercise we work with boolean and equality operators in Python. Interestingly Python uses the words 'and' 'or' 'not' for boolean operators, instead of '&&' '||'. Python also uses the words 'True' and 'False' to denote the boolean types true, and false respectively.

I completed the exercise which was to evaluate some logic statements and correctly guess what the answer should be.

For extra credits I also checked out the equality operators in Python. Here's the list:

== Equal to
!= Not equal to
<> Not equal to
< Less than
> Greater than
<= Less than equal to
>= Greater than equal to

While looking at the page describing Python operators, I came across membership operators, which I found quite interested. Python has two membership operators which can work with sequences such as lists, tuples, and strings.

LPTHW Exercise 27

Exercise 27 is about logic and truth tables. Since I have been programming for a while, I am familiar with this, and am skipping the exercise.

LPTHW Exercise 26 - Test

This is a simple test, where we are given a file with broken code, and we have to fix it. I fixed the file and tested it. Not including it to avoid spoiling anyone's experience.

LPTHW Exercise 25

Exercise 25 is an "even more practice exercise"

In this exercise we practice writing and using functions.

Stuff I learned:
  • We can pop an element from a list, and when we do that the element is removed from the list
  • We can split a String based on a delimiter
  • We can use the sort function to sort a list



Monday, September 26, 2011

Exercise 24 - More Practice

Completed exercise 24. This was a recap of some of the concepts covered till now. We recapped how to use different quotes in strings. We also learned how to format Strings using format character, we recapped how to define and use functions.




Friday, September 23, 2011

Exercise 23 - Read some code

For this exercise, we have to read some code and try to make sense of it. I have picked up 3 samples and will read each one of them.

  1. skills.py
  2. cookme_recipes.py
  3. Game of life
I read through the first two examples. The proved to be a very good starting point. They worked mostly with maps, creating them, getting keys, creating maps where the value is yet another map, etc.

The third one gameoflife.py is an implementation of Conways Game of Life in Python.

Completed reading it. This Python files used classed, functions, and a main function also. Nice experience, I will recommend that everyone try this exercise sincerely.


Exercise 22 - What do you know so far ?

In this exercise I am going to read through all the stuff I have done so far in the course, and then I will make a table of all the symbols, keywords, and concepts encountered in the course thus far.

# Used to comment a single like
+ Addition symbol
- Subtraction symbol
/ Division symbol
* Multiplication symbol
% Modulus symbol
< Less than symbol
> Greater than symbol
<= Less than equal to symbol
>= Greater than equal to symbol
= Assignment symbol
\ Escape character

* Can also precede an argument name given to a function. In this case it means that this variable will accept all the input given to the function as a list


def A keyword used to define functions
import Used to import a module or a symbol from a module

argv Is a symbol from the 'sys' module which contains all the command line arguments passed to a Python script, starting with the name of the script itself

print Prints the specified values to the standard console
raw_input Accepts raw input from a user from the standard console
open(filename) Opens a file and returns a handle to it. By default this function will open the file in read mode, but we can specify a mode and open it for writing, etc
read() A function which can be called on a file handle to read the contents of a file
close() A function which can be called on a file handle to close the file and free up resources on the OS
truncate() A function which can be called on a file handle to remove existing contents of a file to either the current position of the file pointer, or if we provide a size argument then it will be truncated to that size
write() A function which can be called on a file pointer to write to the file
exists() A function which takes a file pointer and determines if that file exists
len() A function which takes data and tells us the size of that data. It accepts a sequence or a mapping


Stuff I learned:
  1. In Python we use the 'print' function to print to the console
  2. In Python function calls need not have () like in Java
  3. In Python we use the '#' character to comment a single line. The C style comment '//' does not work in Python
  4. We do not have to end a statement with a ';' or any delimiter in Python
  5. Python Strings can be delimited by double quotes as well as single quotes
  6. A double quoted string can contain single quotes
  7. It is not compulsory to have a main method in Python
  8. The print function can take multiple arguments separated by ','
  9. When we give multiple values to the print function, it automatically puts a space in between them
  10. Since Python is dynamically typed, we do not need to specify the type of variables, nor do we need any special syntax like 'var' to define variable names
  11. When doing math operations in Python, if all the operands are integers, then the result will also be an Integer. If the operation is a division operation, then the result will be truncated to yield an Integer. However, if even one of the operands is a float, then all operands will be promoted to floating point numbers and the result will also be a float
  12. Python supports formatting of Strings with the % character
  13. There are many formatting characters in Python. %r is one of them. It will print the String representation of any object, by calling the repr() method of that object
  14. When we use %r for formatting, it surrounds the String between ''
  15. We can multiply a String with a number, such as "." * 10 - This will concatenate the String 10 times
  16. Strings can also be concatenated with the + operator
  17. We can specify triple quoted Strings. These can span multiple lines, and can also contain single and double quotes
  18. When we print something with the print statement, it automatically appends a newline character to the String when it is printed. We can override this functionality by ending the print with a ','
  19. raw_input("prompt") can also be given a String which will be used as a prompt
  20. In Python we can unpack a list into multiple variables by assigning a list to multiple variables (see ex13.py)
  21. If we type CTRL-C on the console when the program is expecting input, it results in a KeyboardInterrupt and the program will exit
  22. In Python functions do not have to be delimited with {}. Rather there contents are indented, and the function ends when the indentation comes back to the level before the function


LPTHW - Exercise 21

In this exercise we learn how to return values from functions.





Wednesday, September 14, 2011

LPTHW - Exercise 20

In this exercise, we combine functions and files. We create some functions to operate on files.

New things I learned:
1. We can use the seek() function on a file handle to take the file cursor to a particular position in the file
2. We can give multiple strings to the print function by separating them by a ','

LPTHW - Exercise 19

In this exercise, we reinforce the things we learned in the previous exercise on functions. We also learn that variables inside a function are not connected to the variables outside the functions (scope).

LPTHW - Exercise 18

In this exercise, we learn how to define functions. Functions can be thought of as creating custom commands.

We use the 'def' keyword to create functions. The function's body needs to be indented with the same number of spaces in every line.

We can accept a parameter called *args (args can be replaced with anything else). This I believe takes a list of parameters which can be unpacked into multiple arguments as seen in the function 'print_two'

LPTHW - Exercise 17

In this exercise we will copy the contents of one file to another. In a past exercise, we learned how to read the contents of a file, and in another past exercise we learned how to write to a file. In this exercise, we will read the contents of one file and write it to another file.

The new things I learned in this exercise are:
1. We can use the exists() function to find out if a file exists
2. We can use the len() function to determine the size of data in a file=

Tuesday, September 13, 2011

LPTHW - Exercise 16

In the previous exercise we read the contents of a file. In this exercise we are going to read and write files.

We will open a file in the 'w' mode and then truncate it. Then we accept three lines of input from the user, and append them to the file.



Extra Credit:

In the next example, we comment most of the lines of the solution and also reuse the prompt by using replacement characters.



We need not have called truncate on the fp, since opening a file in 'w' mode automatically truncates it.

Monday, September 12, 2011

LPTHW - Exercise 15

In this exercise, we will read the contents of a file and print them to the console.



Notes:

We use the open(filename) function to get a file handle, and then we use the read() function of the file handle object to read the contents of the file as a string.

I am sure there is a different way to read a binary file, and I am also sure there should be a way to buffer the input in case the file is very large, but read is the simplest way to get the job done. This is much better than Java where we have to jump through tons of hoops to read a file.

LPTHW - Exercise 14

In this exercise we use a value from the command line input to prompt the user.



Questions:

1. The unpacking thing seems to basically work with lists on the RHS and a bunch of variables on the LHS. Not sure if that is right. Will have to find out.

LPTHW - Exercise 13

In this exercise we will learn how to accept command line arguments.



In the script above in the first line we import the 'argv' variable from the 'sys' module. This variable will hold the name of the script and all command line arguments given to it.

We unpack these values and assign them to the variables on the LHS.

Questions:
1. Does importing argv make is available, or does it also turn on the function of accepting command line arguments?

2. Here we assign the values to the variables on the LHS. However, we need to be sure that the command line parameters and the number of variables are the same. This is not always possible, especially when we do not know how many values the user will enter. Perhaps, this issue will be dealt with in a later exercise. I will leave it as is for now, but will try to answer it if it is not dealt with in a later exercise.

LPTHW - Exercise 12

In this exercise, we will provide some text to the raw_input() function as a parameter. This text will be used as the prompt. This is much easier than the previous exercise, where we first printed something (as a prompt) and then asked for input using the raw_input() function.



Extra Credits:

We can read the documentation of any function using the pydoc command. To quit the documentation, press 'q' on the command prompt.

LPTHW - Exercise 11

In this exercise we are going to accept input from the user.



Notes and extra credits:

When we print something with the print statement, it normally ends with a newline. We can prevent the new line by ending the print statement with a ',' as shown in the example above.

The raw_input() function is used to read input from the console. It will read one line of input, and pass it to the program with the ending newline stripped out.

It seems we can load the 'readline' module to provide some elaborate editing and history features.

In the output of the above program, all the instances of %r are replaced by the output of running __repr() on the arguments. The output is always delimited with ''. Since the height also uses a ' within it, it must be escaped.

LPTHW - Exercise 10

In this exercise, we look at some more printing and escape characters. The "\" is the escape character in Python (just like in many other programming languages).



Extra Credit:

Escape characters are used to change the meaning of the character following it. For example \t will print the 'tab' character instead of 't'. All escape sequences supported by Python are listed on this page from the Python docs.

I tried replacing the triple double quotes in the example above with triple single quotes. When I ran the example, it ran just like the one with triple double quotes. I am not sure if there is any difference between them. Maybe if we use triple single quotes, then we can embed triple double quotes in them.

%s is better for printing because it is replaced by the String value, whereas %r is replaced by what is returned by the __repr function of the object (usually this is surrounded by double quotes).

LPTHW - Exercise 9

In this exercise, we executed some more printing code. The new concept I learned in this exercise, is that we can use triple quotes to represent a string which can span multiple lines.

Wednesday, August 31, 2011

LPTHW - Exercise 8

Completed exercise 8.

Nothing much to report in terms of thought process, etc for this exercise.

Thursday, August 4, 2011

LPTHW - Exercise 7

In exercise 7, we learn a bit more about printing. I typed the program, added some comments to explain what it does and got it to work.



Some observations:
  • Ending a print statement with a ',' as we see on line 29, prevents a newline from being printed
  • Multiplying a String, concatenates the String with itself, that many times (as seen on line 11)

LPTHW - Exercise 6

In the last exercise, we learned about variables and also introduced String formatting. In this exercise, we learn more about Strings and text.

First, I typed the program as is, and got the expected output.



Extra Credit:

Next, I commented the code, and also counted the number of times we put a String inside a String (it is indeed four times).



Some Observations:
  • When we concatenate multiple Strings a space character is not added between them, the way print adds it, when we try to print multiple Strings. So if we want to print multiple Strings without spaces between them, then we should concatenate them with the + operator and print the concatenated result.
Some questions:

LPTHW Exercise 5

LPTHW's Exercise 5 is a nice introduction to variables and printing.

I typed the program as is (along with some comments to explain what the program does), and got the expected output.



Extra Credits:

Next I replaced all the variables which start with 'my' such that the names do not contain 'my'. Got that code to also do it's work.



Then I looked up the documentation for String formatting in Python, and learned a few interesting things.
  • Formatting is actually facilitated by a function called '%' in Python String. So basically when we type "hello %s" % name what we are actually doing is calling the '%' function of the String "hello", and giving it the variable 'name' as an argument. If we need to supply only 1 argument, then we can give it a single variable, however, if we need to supply multiple arguments, then we must use a tuple. Like this "hello %s %s" % (first_name, last_name)
  • There are many formatting characters in Python. I checked out the meaning of %r as the exercise mentions. %r will print the String representation of any Python object, by calling the objects repr method. This is interesting. So this is how Python gets a String representation of an object. In Java this is done by invoking the function toString()
Next I created some variables which convert Pounds to Kilograms, and Inches to Centimeters, and that too works properly.


Wednesday, August 3, 2011

LPTHW - Exercise 4

Starting with exercise 4, where we learn about variables. I typed in the code, and got an error when I tried to run it.



Error:
File "ex4.py", line 11
print "There are" only", drivers, "drivers available."
^
SyntaxError: invalid syntax

Solution: The problem is the double quote after 'are'

Here is the correct solution:



Here is the output:

There are 100 cars available.
There are only 30 drivers available.
There will be 70 empty cars today.
We can transport 120.0 people today.
We have 90 to carpool today
We need to put about 3 in each car.


Questions:
  1. An interesting observation : When we give multiple values to print (separated by commas), a space is automatically put in between them. This is really nice, but what if we do not want to the space?

Observations:
  1. In python we do not have to give the type of variables (because Python is dynamically typed), and we do not need to use any special keyword like var, or def before declaring a variable,. This is in contrast to other languages which normally require something before a variable name.

Extra Credit:

The error described on the page:
Traceback (most recent call last):
File "ex4.py", line 8, in
average_passengers_per_car = car_pool_capacity / passenger
NameError: name 'car_pool_capacity' is not defined
This means that a variable of the name 'car_pool_capacity' had not yet been defined. This could happen if the author either forgot to define the variable, or did a typo when defining it. In this case it looks like a typo because the actual variable is 'carpool_capacity'.

Why do we use 4.0 instead of 4 ?
4.0 is a floating point number, while 4 is an integer. Floating point numbers can represent fractions, while integers cannot.

With some experimentation with Python, I realized that if we do operations with all integers, then the result will also be an integer. If the operation of a division operation and the result is actually a fraction, then it will be truncated to yield an integer.

However, if even one of the numbers is a floating point number, then the rest will be promoted to floating point numbers to yield a floating point number.

i = 4
j = 3
i/j
answer: 1

i = 4.0
j = 3
i/j
answer: 1.3333

i = 4
j = 3.0
i/j
answer: 1.3333