Computer science is about solving problems, preferably in a beautiful and artistic way. Computers are used in every discipline from medicine (medical robotics, analysis of the spread of disease, design of drugs) to the visual arts and we sure you have seen a Pixar film recently. Computer science is one of the newest disciplines; it has completely transformed our world and will continue to do so.
Above all else, computer science is a creative discipline, mixing some of the best aspects of engineering, art, science, language, and mathematics. Learning about computation will change how you view problems in every discipline, and how you think about solutions to those problems.
Python shares many similarities with other programming languages, including Java and C++, and once you have learned Python, these other languages will not be difficult to pick up. Python is a fairly popular language, and it is also fairly easy to get started with.
Let us get started. A computer program is made up of instructions that a computer follows. Here is a simple program with one instruction:
This program causes the computer to print the word
Hello in the console window. Notice that the quotation marks around
Hello are not printed.
Here's another program:
In this multi-line program, commands are executed in the order they appear.
As the Python interpreter runs a program, the interpreter keeps track of the line number that is currently being executed. The bookmark used to keep track of the line number is called the program counter.
The program counter always starts out pointing at the first line of the code in the program you run. It executes that line of code. Depending on what that line of code says, one of two things happens:
Why would we ever want the interpreter to suddenly jump to a new line of code? We'll see many reasons, but the first is to write and use our own commands, called functions, that are made up of a chunk of lines of code.
By giving a name to a chunk of lines of code, we can easily re-use that section of code without having to retype all those lines every time. Here's a program that defines our own two functions,
Notice that nothing is printed when you run this program. We have instructed Python that there are two functions, and described them, but have not actually instructed Python to run either of the functions.
Function definitions have two parts: a header, and a body. The header gives the name of the function you want to define (as well as some other things we'll see later). The body is a set of lines of code that tell what the function does. Each line of the body must be indented by pressing the tab key. The indentations tell Python where the function body begins and ends.
The header uses the keyword
def (short for define), the name of the function you'd like to define, parentheses after the name of the function, and a colon. So the header for the first function is:
The body of the first function is
To tell the interpreter to actually run the body of a function, you use a function call. To write a function call, write the name of the function followed by parentheses.
When the program counter reaches a function call, the interpreter takes a note of where the program counter is, moves the program counter to the first line of the body of the appropriate function definition, and executes the lines of code in the function. When the interpreter gets to the end of the body of the function, the program counter jumps back to just past the function call, and Python continues from there.
Lets trace out the program counters locations as the above program executes:
say_hello, which is
print("hello")This line causes
helloto be printed.
say_hello, and so it jumps back to just past the call of
say_hello, which is the line containing the second call of
say_hello, which is
print("hello")This line causes
helloto be printed.
say_hello, and so it jumps back to just past the second call of
say_hello, which is the line containing the call of
why_goodbye, which is
print "I don't know why you say goodbye."This line causes
I don't know why you say goodbye.to be printed.
why_goodbye, and jumps back to the line containing the call `print(â€œI say hello.â€)
I say hello.is printed. But this call to
It is very important to understand the order in which Python executes lines of code. Stepping through code one line at a time in your mind in the order that Python executes those lines is a very good habit to get into.
Objective: Write and call your own functions to learn how the program counter steps through code.
You will write a program that introduces you and prints your favorite number.
Hello, my name is X.and
I am a Y.on two separate lines, where X and Y are replaced by whatever you like.
say_introductionso that the introduction is printed before the favorite number.
Test your code after steps 2 and 4: take a minute to think through what you expect to happen, and then press the run button.
Here is a solution. No peeking until you have solved it yourself!
Building higher-level concepts from simpler pieces, and then working with those higher-level concepts, is called abstraction. Abstraction is a major tool in computer science that we'll come back to over and over.
Abstraction hides the details of how things work. Functions are our first example of abstraction. We defined a few functions, each in terms of a sequence of simpler commands. Once we defined those functions, we were able to just use them without thinking (too much) about how they worked.
Abstraction is not just important in computer science. When I press the gas pedal on my car, a lot of stuff happens, but because I have the higher level â€œpush-gas-pedalâ€ concept, I don't have to think about the details of what is going on in the internal combustion engine to make my car go.
It might be fun to consider any other hobby or academic discipline you are interested in and explicitly identify the uses of abstraction, and levels of abstraction.
Here's another big win for functions. You can use a function someone else wrote, without knowing exactly the internal details of the function. Let's look at an example:
The first line says that this program will use the
print_date_and_time function from the
simplefunctions library of functions. (In Python, such a library is called a module.) The program then calls the
print_date_and_time function. When this function is called, the interpreter saves the current value of the program counter, sets the program counter to the beginning of the print_date_and_time function somewhere in the
simplefunctions module, executes the code it finds there, and then resets the program counter to the original, saved value.
Just like the print command, functions can take parameters â€“ additional information that influences the results of calling the function.
When making a function call, we write the values of the parameters inside the parentheses. We say that we pass the parameters to the function at the point of call. Functions may take multiple parameters, in which case we separate them by commas when we call the function. Here's an example:
There are a few things to notice. First, there's the
import command. This first line says â€œgo to the
cs1lib_web module; we'll be using the
start_graphics functions from there.â€
Then we define the
draw function. This function isn't executed quite yet; we are just defining it. Python doesn't even look inside the function body yet. Instead, Python jumps to the line
The function call
start_graphics does two things:
We never actually have to call the function
draw ourselves in this case. Instead, we passed the name of this function as a parameter to
start_graphics, and that function runs
draw. Yes, the parameter that we pass to
start_graphics is not a number, but rather a function.
start_graphics expects to be given a function as a parameter.
What do we know about
start_graphics? We know that it enables us to do graphics by opening a window on which graphics appear, and we know that it runs a function that we pass to it as a parameter. We don't know how it does what it does, however. Abstraction at work!
Let's look at what happens when
start_graphics gets around to calling
draw calls the function
clear, which clears the window.
draw calls the function
draw_circle, passing it three parameters. The first parameter, 125, says to draw the circle at x coordinate 125 in the window. The second parameter, 100, says to use the y coordinate 100. The third parameter, 50, says that the radius of the circle should be 50. The final line of the
draw function calls the
draw_circle function again, with different parameters.
It is very important to understand the order in which Python executes lines of code. Here is an exercise. Grab an index card or piece of paper, and place it under the first line of code in the program. Move the card in the same way the program counter would move. First, the import statement. Then, the line
def draw. After that, jump past the body of the
draw function, since this is just the definition of the function. Jump all the way down to
start_graphics. We know that this function calls
draw. So eventually, we jump back up to the first line of the body of
draw, and step through the lines in
Stepping through code one line at a time in the order that Python executes those lines is not very exciting, but a good habit to get into. You should step through every piece of code you see as you are learning Python.
We glossed over what the coordinates passed to the
draw_circle functions really mean. When we open a window for graphics, there's a coordinate system within the window. Coordinates correspond to pixels in the window, with (0, 0) at the upper left corner of the window:
The coordinates (125, 100) mean the pixel that is 125 pixels to the right and 100 pixels below the upper left corner. The above diagram shows a rectangle with a black outline one pixel thick and a red fill, with its upper left corner at (3, 1) and its lower right corner at (9, 5).
Think of it this way: starting from the upper left corner of the graphics window, x coordinates increase to the right, and y coordinates increase down from the top. If you think about how x and y coordinates usually work in mathematics, graphics on a computer doesn't quite match up. The x direction works, but in math, increasing y coordinates go up, whereas in computer graphics, increasing y coordinates go down.
What do the parameters passed to
draw_circle mean? The first two parameters give the x and y coordinates of the circle's center, and the third coordinate gives the circle's radius in pixels. Here's a simple exercise for you to try: What would you see if you called
draw_circle(0, 0, 100)?
Objective: learn how to call drawing library functions that take parameters, in order to draw a desired complex picture.
Write a program that causes a yellow smiley face to be drawn on the screen. You have a 200 by 200 window available.
Draw the outline of the face. Put your code for drawing the outline after the line
# draw the outline of the face. (Lines that begin with
# are ignored by the computer, and are for human readers only.
Draw the eyes. Put your code for drawing the eyes after the line
# draw the eyes.
Bonus challenge. Draw the mouth. Hint â€“ draw a circle, and then erase the top part of it by drawing some sort of yellow shape.
Here is a solution. No peeking until you have solved it yourself!
Computer programs are not just for computers. Good code should do two things:
A well-written program is more than a machine for solving a problem â€“ it is in a real sense a description of a solution to a problem. How to write good, human-readable code is a major focus of this course, and we'll come back to it again and again.
Let's look at the following bad program.
What does this program do? Does it describe how to solve a problem? What's the problem? Is this is a good solution? Could you modify it easily to solve a more interesting problem, without even knowing what the program does?
In this case, the program is short and you could figure out what it does by running it with Python. It would still be a lot of work to figure out what each line of code was intended to do, although we might get a high-level picture from Python.
from cs1lib import * tells Python that you want to be able to use every function from the
cs1lib module, freeing us from having to specify each and every function we intend to use.)
You can use the
# symbol in Python code to indicate code that Python should ignore. On a line of code, everything after the pound symbol is called a comment, and is ignored by Python â€“ it's just there for human readers.
We can now see exactly what the program is intended to do, and also which lines of code accomplish which parts of the solution.
How much should you comment your own code? Here are some guidelines:
Good comments add new information, but that does not mean you should comment every single line of code. Here's a distracting comment that is not useful:
draw_rectangle(280, 310, 25, 40) # draw a rectangle
We can see from the function name that this line draws a rectangle. A more useful comment would tell us what we are trying to do with the rectangle (in this case, draw a door). Another comment might tell us the fill color:
# draw the door set_fill_color(.6, .5, .3) # light brown draw_rectangle(280, 310, 25, 40)
Organizing code into function definitions and function calls is an example of abstraction, and also is an example of good style. It's probably not hard to guess that the function
draw_rectangle draws a rectangle. We could have drawn the rectangle by drawing four individual lines using four function calls, but it's better style to use a single, appropriately specific function call.
In the previous example, we saw a few new graphics functions:
draw_rectangle draws a rectangle, given four parameters. The first two give the x and y coordinates of the upper left corner of the rectangle, the third parameter gives the rectangle's width, and the fourth parameter gives the rectangle's height. So the call
draw_rectangle(200, 250, 130, 100) draws a rectangle with an upper left corner at (200, 250) and a lower right corner at (330, 350).
draw_triangle takes six parameters, which it groups into three consecutive pairs. Each pair gives the coordinates of one vertex of the triangle. So the call
draw_triangle(200, 250, 330, 250, 265, 200) draws a triangle with vertices at (200, 250), (330, 250), and (265, 200).
set_fill_color says that until told otherwise (by a subsequent call to
set_fill_color), we are drawing all filled shapes in the color specified by its three parameters. The parameters give the fraction of red, green, and blue (in that order) that, when mixed together, form the color. White would be (1, 1, 1), black would be (0, 0, 0), pure red would be (1, 0, 0), pure yellow would be (1, 1, 0) (mixing red and green), and so forth. Play with changing the parameters to
set_fill_color in the program that draws the house.
disable_stroke just says that when we draw rectangles, circles, and triangles, draw just the inner filled part, not the outline. See what happens if you comment out the call to
disable_stroke by putting a
# in front of it.
Python ignores certain types of whitespace, such as blank lines and spaces after commas. You should use blank lines to group your code into logical segments. A good rule of thumb is that there should be a blank line roughly every 3â€“10 lines of code. If you have fewer blank lines, look hard to see whether you can break down your code into smaller chunks. You can think of these blank lines as serving the same purpose that new paragraphs do in English writing.
It's also good style to put a space after every comma, just as you would in written English.
Bear in mind that whitespace at the beginning of a line is very significant. In Python, indentation indicates structure. You've already seen how the body of a function is indented by one tab stop. We'll see plenty of examples of indentation as we go along.