Explore 1

Beautiful Code
Ka-Ping Yee, March 5, 2003

On web pages, i'll try to stick to the convention that user input is blue and program output is purple. When you see this:

Q42. What is the meaning of life?

...that means i want you to figure out the answer to the question and write it down. When you've finished the session, send your answers to me in an e-mail message.

Okay, let's go!

0. Lovely Spam

Start Python and type in print 'spam'.

cory% python
Python 2.2.2 (#1, Oct 31 2002, 16:12:04) 
[GCC 3.2] on sunos5
Type "help", "copyright", "credits" or "license" for more information.
>>> print 'spam'
spam
>>>

The interpreter will read your instructions as you type them in and execute them one by one. To quit the interpreter, type Control-D (in Unix) or Control-Z (in DOS). To create a Python program, you just put these instructions into a file. For example, create a file called spam.py containing this line:

print 'spam'

Now you can execute the file by typing python spam.py, like this:

cory% python spam.py
spam
cory%

Congratulations. You've written your first Python program.

In general, putting commands into a file and executing the file has the same effect as typing all those commands into the interpreter. There's only one important difference, which we'll investigate below.

1. Help

Try typing help in the interpreter.

>>> help
Type help() for interactive help, or help(object) for help about object.
>>>

Oh. Looks like we should be typing help(), with the parentheses. Let's try that:

>>> help()

Welcome to Python 2.2!  This is the online help utility.

If this is your first time using Python, you should definitely check out
the tutorial on the Internet at http://www.python.org/doc/tut/.

Enter the name of any module, keyword, or topic to get help on writing
Python programs and using Python modules.  To quit this help utility and
return to the interpreter, just type "quit".

To get a list of available modules, keywords, or topics, type "modules",
"keywords", or "topics".  Each module also comes with a one-line summary
of what it does; to list the modules whose summaries contain a given word
such as "spam", type "modules spam".

help> 

Have a look around. Try typing modules, keywords, or topics at this point and see what happens. Browse around a bit. I don't expect you to understand all the documentation right away, but you should know that it's there. Try looking up the documentation for print.

When you're done with help, type quit. The prompt will change from help> back to the standard Python prompt, >>>.

2. Numbers

As i demonstrated in class, you can enter numerical expressions into the interpreter and it will evaluate them for you.

>>> 3 * 4
12
>>> 3 ** 4
81
>>> 3 ** 40
12157665459056928801L
>>> 3 ** 0.5
1.7320508075688772
>>>

The double asterisk ** is the exponent operator. The extra L at the end of 12157665459056928801L stands for long, and indicates that this number is a long integer. In Python, long integers can be as big as you want. You might find it fun to generate some enormous numbers. If you get carried away and the interpreter gets stuck for a while calculating a huge number, you can always stop it by typing Control-C.

3. Strings

Strings are another kind of value. Strings contain sequences of characters. You can enter a string using single or double quotes; it doesn't make any difference, except that if you want to use a single-quote within the string, you will have to put double-quotes around it, and vice versa. If you write a single quote inside a string that started with a single quote, Python has no way to tell that it isn't the end of the string.

>>> 'abc'
'abc'
>>> "abc"
'abc'
>>> 'abc'def'
  File "<stdin>", line 1
    'abc'def'
           ^
SyntaxError: invalid syntax
>>> "abc'def"
"abc'def"
>>>

By convention, if you have a choice between single quotes and double quotes, use single quotes. They're slightly easier to type and visually lighter to read. You can also see from the first four lines in the above example that Python chooses single quotes when it has the option.

What if you want to write a string that contains both single-quotes and double-quotes? Then you have to use a backslash in front of the character you want to protect. A backslash within a string gives special meaning to the character that follows it. Backslash-quote always means "put in an actual quotation mark here".

>>> 'abc\'def'
"abc'def"
>>> print 'abc\'def'
abc'def
>>> 'abc\'def\"ghi'
'abc\'def"ghi'
>>> print 'abc\'def\"ghi'
abc'def"ghi
>>> 

Notice that there's a difference between how you represent a string and what the string actually contains.

When you type in 'abc\'def', you have entered a string containing seven characters, even though what you typed has eight characters between the quotation marks. When the interpreter displays a result to you, it always shows the representation of the result. It gives you something that you could type back in to describe the result. Python tries to choose the shortest possible representation, so it displays "abc'def" instead of 'abc\'def'. Both representations describe the same seven-character string. Printing a string displays just the actual characters in the string.

Q1. Why does the interpreter report the representation of each result instead of just printing the result?

(Hint: try print 3. Now try print '3'.)

To put a backslash into a string, you put another backslash in front of it. Two other common backslash-codes are \n, which represents a newline character, and \t, which represents a tab character. There are other codes, too, but you don't need to worry about them right now, and you can always look them up.

>>> 'spam\nspam\nspam'
'spam\nspam\nspam'
>>> print 'spam\nspam\nspam'
spam
spam
spam
>>> 'ah...\n\n\n\t\tchoo'
'ah...\n\n\n\t\tchoo'
>>> _
'ah...\n\n\n\t\tchoo'
>>> print _
ah...


                choo
>>> 

You can see that the newline and tab characters reveal their true nature when you print them out. In this example we've used _ (a single underscore), which is a special symbol for "the last result". It's just a convenient way to save typing when you're talking to the interpreter.

For long strings that contain many lines, you can use triple-quotes. When you do this, the string will continue over as many lines as you want until a matching triple-quote is found. Again, it doesn't matter whether you use ''' or """.

>>> '''spam
... spam
... spam
... lovely spam'''
'spam\nspam\nspam\nlovely spam'
>>> print _
spam
spam
spam
lovely spam
>>> 

Notice that the prompt changes from >>> to ... after you've entered the first line. This means Python knows that you're not finished, and it's waiting for you to enter another line of input before it will evaluate the expression.

4. Functions

Python comes with some useful built-in functions for manipulating things. One good example is len. Try just typing in len and see what you get.

>>> len
<built-in function len>
>>>

That's a pretty strange-looking representation. All it means is that len is a function.

To call a function, put parentheses after it, and specify the arguments in the parentheses. By convention, we never put spaces between the function name and the parenthesis, and never put spaces just inside the parentheses. This distinguishes the use of parentheses for calling functions from the use of parentheses to group expressions.

The len function takes one argument, and tells you how long it is.

>>> len('abc')
3
>>>

What happens if you ask for the len() of a number? Try it.

Try typing help(len). You can get an explanation of many functions this way. Try familiarizing yourself with these built-in functions:

abs    chr     hex     oct    ord    round

Another interesting function is repr(), which generates the representation of something. The result of repr() is always a string.

>>> repr(3)
'3'
>>> repr('abc')
"'abc'"
>>>

That's interesting.

Q2. Why did we get two sets of quotation marks in response to repr('abc')?

Maybe this will help:

>>> 'abc\\def'
'abc\\def'
>>> print 'abc\\def'
abc\def
>>> repr('abc\\def')
"'abc\\\\def'"
>>> print repr('abc\\def')
'abc\\def'
>>>

What happens if you do repr(repr('abc'))? How about repr(repr(repr('abc')))?

What do you think will be the value of len(repr(repr(repr('abc\\def'))))? Work out the answer on paper before you actually try it. If you don't understand what's going on, ask me.

5. Types

Every value in Python has a type. You can find out the type of anything by asking the type() function, like this:

>>> type(3)
<type 'int'>
>>> type(0.5)
<type 'float'>
>>> type(3**3**3)
<type 'long'>
>>> type('spam')
<type 'str'>
>>>

There is also a special thing called None that has its own type:

>>> None
>>> type(None)
<type 'NoneType'>
>>> repr(None)
'None'
>>>

Notice that when you type in None, the interpreter doesn't print anything. That's because, as a special case, the interpreter doesn't display the result when it's None; in all other cases the interpreter displays a representation of the result.

The purpose of None is to have a value to store or return when you want to indicate that there's nothing, no answer, or no result. It can come in pretty handy sometimes.

What type is the len function? Try it and see what you get.

The common types are also available by their own names:

>>> int
<type 'int'>
>>> str
<type 'str'>
>>> type(int)
<type 'type'>
>>> type(type(3))
<type 'type'>
>>>

As you can see, the types are values too, and they all belong to their own type called, surprisingly enough, "type".

The types can also be called, just like functions. In general, when you call a type, it will try to convert its argument to a member of the type.

>>> str(3)
'3'
>>> int(3)
3
>>> int('3')
3
>>> int('100', 7)
49
>>>

int() has the special feature that you can also supply a second argument, the base (or radix) of the number. "100" in base 7 has the decimal value 49.

What happens when you try to take the int() of a floating-point number? Or the int() of a string containing a floating-point number? How about the int() of a string with some spaces before or after the number?

Play with int(), str(), and float() until you are comfortable with what they do.

Q3. How would you convert a string like '1.62' into a floating-point number?

Q4. What is the difference between str(x) and repr(x)? Does it matter whether x is a number or a string?

6. Operators

Here are some common operators:

+    -    *    /    %    **

|    &    ^    <<    >>

<    ==    >    <=    >=    !=

and    or    not

Experiment with them until you're familiar with what they do. Try using them on strings as well as numbers. What happens if you add two strings? What happens if you add a string and a number? Or multiply a string and a number?

If you can't guess what one of these operators means, see if you can find out with help().

7. Truth

You probably noticed that the result of a comparison, like 'a' < 'b', is always 0 or 1. Up to version 2.2, Python uses 1 and 0 to represent true and false, just like C. In version 2.3 (currently in alpha) and beyond, true and false will have their own values, named True and False, and their own type, the Boolean type.

Every type has one value that is considered false. For integers, it's 0. For floating-point numbers, it's 0.0. For strings, it's the empty string.

The not operator returns 1 or 0, like a comparison. But the and and or operators are different. Try some of the following:

1 and 2
1 or 3
'abc' and ''
'abc' and 'def'
'abc' or ''
'abc' or 'def'
'spam' and 0
'spam' and 1
1 == 2 and 'yes' or no'
1 == 1 and 'yes' or no'

Q5. Explain what and and or do.

Hint: Python tries to avoid unnecessary work.

8. Variables

As in other languages, you can assign any value to a variable using the = operator. Variable names must start with a letter or underscore, and are allowed to contain letters, digits, or underscores.

>>> a = 3 ** 4
>>> print a
81
>>> b = str(a) + ' flying llamas'
>>> print b
81 flying llamas
>>> b
'81 flying llamas'
>>>

Things like len and int are actually the names of variables that refer to things, in this case a function and a type.

Be careful not to confuse = with the == operator.

9. Statements and Expressions

Earlier I mentioned that there's one important difference between the behaviour of commands when you enter them into the interpreter, and when you run a script.

Have you tried entering any of the examples and running it as a script? Try this:

3 + 4
print 5 + 6

Put the above into a script and run it. What happens? How is that different from what happens when you type those lines into the interpreter?

The two lines are different in an important way. The first line is an expression. It is evaluated and comes out to a value. The second line is a statement. It commands Python to do something; we say that it is executed. The statement happens to also contain an expression, the expression 5 + 6.

A function call is also an expression. For example, the call len('abc') has the value 3.

Now try these in the interpreter:

a = 3 + 4
b = print 5 + 6

What happened? Do you understand why?

Q6. How does the interpreter treat statements and expressions differently?

Q7. What's different about how they are treated in a script?

10. Control Statements

Python has control statements that are very similar to those in most common languages. For making decisions, it has an if statement like this:

if a < 0:
    print 'negative'
    a = -a
elif a > 0:
    print 'positive'
else:
    print 'zero'

You'll notice a couple of unique things about this code.

First, there is no keyword that marks the end of the if statement. The contents of each part of the statement are determined by the fact that they are indented. This may seem strange to you at first, but actually it's quite natural. You can always tell the block structure of something just by looking at it. However, it also means that in order for your program to work, it must be indented consistently.

By convention, indentation is always four spaces per level. This is pretty much universal in all Python code, and you should stick to it.

Second, "else if" is abbreviated elif.

Unlike some other languages, you don't need to put parentheses around the condition. In general, it helps to make your program more readable if you try to minimize the amount of punctuation. You just state the condition right after the if and then introduce the block with a colon. Indented blocks in Python are always introduced with a colon.

The while statement looks very similar:

a = 10
while a > 0:
    print a 
    a = a - 1
print 'blastoff'

The continue command inside a while loop ignores the rest of the block and jumps immediately back to the beginning of the loop. The break command immediately breaks out of the loop, proceeding with the next statement after the end of the loop.

When you're entering code directly into the interpreter, once you've started a block, the prompt will change to ... so you can enter more lines. However, the interpreter requires that you enter a blank line at the end of a block so it knows when you are finished. So if you were typing the above example directly into the interpreter, you would have to add a blank line just before the print statement. You don't have to do this if you're writing a script file.

As your programs get longer you will want to move towards editing them in files anyway. You can edit your program in a file and then test it in the interpreter using the execfile function. For example, if the above example was in a file called blastoff.py, then you could do this:

>>> execfile('blastoff.py')
10
9
8
7
6
5
4
3
2
1
blastoff
>>> 

Create a file named addition.py containing just this:

1 + 1

What happens when you do execfile('addition.py')?

Remember that function calls are expressions, so they have values.

Q8. What is the value of execfile('addition.py')?

Hint: try comparing it to things. Also try putting print 1 + 1 in the file, and see if it makes any difference.


Okay! Well, now you should know all you need to know to do the first assignment.

If you have any questions about these exercises or the assignment, feel free to send me e-mail at bc@zesty.ca.