# Writing Python Programs

So far, we’ve discussed how to use the UNIX command line to filter and modify files. We’ve also discussed how to use the Python interactive interpreter to play around with Python expressions and statements. Our next task is to learn how to put a punch of Python expressions and statements in order, and put them in a file. This is what’s known as a Python program or “script.” (The words “program” and “script” sound scary and technical, but they’re meant in senses of those word that you’re already familiar with—“script” or “program” as in a list of things that you want to happen.)

## Using a text editor

In order to write scripts, we need to be able to make plain text files. A “plain text” file is a file with text in it but no other weird formatting information, like you’d get with (e.g.) Microsoft Word. There are many text editors out there, with different benefits and drawbacks. Two that I can vouch for:

In the following two sections, I’m going to show you how to use these text editors to edit a plain text file.

After installing your text editor, launch it. Type the following text into the window:

``````print("Hello there")
``````

Congratulations, you’ve just written a Python program! It’s a very simple program—it only has one statement, which causes the string `Hello there` to be written to output.

Save the file to your hard drive, then open a Terminal window and navigate to the folder where you saved the file. Type the following on the command line:

``````\$ python hello.py
``````

You should see the string `Hello there`.

## Programming Python

Okay! Now we’re ready to write some actual Python programs.

### Programs are a sequence of statements

So what is a program? Well, a program is a sequence of statements that we want to computer to execute, arranged in the order we want the computer to execute them.

An “expression,” if you remember, is like asking the computer a question: “Computer, what’s three plus five?” or “how many letters are in the word ‘abcedarian’?” A “statement” is more than asking Python to answer a question: a statement asks Python to change the state of the world.

We’ve seen a few statements so far, such as when we’ve assigned values to variables in the interactive interpreter:

``````>>> x = 3 + 5
``````

In the above example, we’ve asked the computer to tell us what 3 + 5 is… but we’ve also asked it to do something: store that value in a variable called `x`.

Another example of a statement is `print`, which changes the state of the world by printing the value of an expression to the screen:

``````>>> print(3 + 5)
8
``````

Again, above we’ve asked the computer a question (the expression `3 + 5`), but we’ve also asked it to do something (display it to the screen).

As an example of a sequence of statements, create a new file on the server and call it “statements.py”. Cut and paste this into it:

``````3 + 5
``````

Now upload that file to the server and run it using Python, like so:

``````python statements.py
``````

(Make sure you’re in the same directory as the Python file when you type the above command.) What happens? Nothing! That’s because we’ve asked Python to evaluate the statement `3 + 5`… but we didn’t tell it to actually do anything with that value. Open the file again and make this change:

``````print(3 + 5)
``````

And run the script again. You should see the number `8` printed to the screen.

Open the file again and put some more statements in there:

``````text = "This is some text."
text_snippet = text[-5:]
print(text_snippet)
``````

Run the program and you should see the following output:

``````text.
``````

In the above example, we have some expressions (such as the expression ```"This is some text."``` which creates a string value; `text[-5:]` which evaluates to a slice of the named string; and `text_snippet` which evaluates to the string assigned to it earlier in the program) and some statements that use those expressions (assigning to the variables `text` and `text_snippet`, then `print`ing the value in variable `text_snippet`).

Learning how to program Python is all about learning how to write expressions, then use those expressions in statements to make changes to the state of Python, or to display things to output.

### Acting on every line in standard input

We’re going to start writing Python programs by writing programs that work a lot like UNIX command-line tools: by reading one line from input at a time, making a decision about that line or modifying that line, and then printing output back to the screen.

Here’s the first program. Cut and paste it into a file called `cat.py`:

``````# our very first program
import sys
for line in sys.stdin:
line = line.strip()
print(line)
``````

This program has some boilerplate in it that I won’t explain in too much detail right now, but just to give you an idea:

• The line `import sys` tells Python that we want to use functions and variables defined in a “module” called `sys` (more about this later in the course!)
• `for line in sys.stdin` is a way of telling Python, “Hey, all the code after this line? I want to you run that code for every line that you read from standard input.”
• The first line of the file, `# our very first program`, is a “comment.” A comment is a part of the program that the computer will ignore. We can use them to make notes in our program, e.g., to explain what a particular part of the program does so we can remember what we meant when we’re looking at the file later. You can make comments in Python by putting the hash character (`#`) anywhere—any text after the hash character counts as a comment.

Make sure that lines 4 and 5 (`line = line.strip()` and `print(line)`) are “indented” over using a tab or spaces. (You can use however many spaces you want, as long as both lines have the same number of spaces at the beginning.)

To run this program, save it, and then in your terminal window, type

``````\$ python cat.py
``````

Type in a few lines, then hit Ctrl+D. (You may need to hit Ctrl+D more than once.) What happened?

That’s right—`cat.py` is a very simple “clone” of the `cat` command-line tool in UNIX. You can use it to display the contents of a file:

``````\$ python cat.py <sea_rose.txt
``````

This should display the contents of `sea_rose.txt`.

Wait, why did we do `line = line.strip()`? That’s a good question! Here’s an exercise: trying removing that line, and then re-running the program. You’ll find that you get an extra line after each line that you print out! Weird. The reason for this is two-fold: (1) when Python reads a line in from standard input, it includes the new line character (`\n`) in the string; (2) the `print` statement automatically adds a new line when it displays a string. So! In order to avoid printing TWO new line characters (the one originally in the string, and the one that `print` adds), we have to use `.strip()` to remove whitespace (i.e., spaces, new lines, tabs) etc. from the end of the string. Good catch!

### Mutating lines

This program isn’t very interest on its own. Here’s how we’re going to make it more interesting. Instead of just printing the value in variable `line`, let’s write an expression on that line that evaluates to the string, but with some transformation applied.

So, for example, let’s write a program that prints out only the first ten characters of each line:

``````import sys
for line in sys.stdin:
line = line.strip()
print(line[:10])
``````

Save this modified version of the program with a different filename—`experiment1.py`, for example. Run this using `sea_rose.txt` as input, like so:

``````\$ python experiment1.py <sea_rose.txt
``````

and you should get the following output:

``````SEA ROSE

Rose, hars
marred and
meagre flo
spare of l

more preci
than a wet
single on
you are ca

Stunted, w
you are fl
you are li
in the cri
that drive

Can the sp
drip such
hardened i
``````

Or, try this:

``````import sys
for line in sys.stdin:
line = line.strip()
print(line.title().swapcase())
``````

Save this as a different file (say, `experiment2.py`) and run it using Python, passing `sea_rose.txt` as input. You should get the following output:

``````sEA rOSE

rOSE, hARSH rOSE,
mARRED aND wITH sTINT oF pETALS,
mEAGRE fLOWER, tHIN,
sPARE oF lEAF,

mORE pRECIOUS
tHAN a wET rOSE
sINGLE oN a sTEM --
yOU aRE cAUGHT iN tHE dRIFT.

sTUNTED, wITH sMALL lEAF,
yOU aRE fLUNG oN tHE sAND,
yOU aRE lIFTED
iN tHE cRISP sAND
tHAT dRIVES iN tHE wIND.

cAN tHE sPICE-rOSE
dRIP sUCH aCRID fRAGRANCE
hARDENED iN a lEAF?
``````

Pretty cool, huh? We can now write programs that behave like simple UNIX command-line tools that modify each line of input as it comes in. And because our programs run on the command-line, we can use pipes and redirection to combine their output! For example, we can pipe the output of running `experiment1.py` on `sea_rose.txt` so it’s the input of `experiment2.py` like so:

``````\$ python experiment1.py <sea_rose.txt | python experiment2.py
``````

The output will look like this:

``````sEA rOSE

rOSE, hARS
mARRED aND
mEAGRE fLO
sPARE oF l

mORE pRECI
tHAN a wET
sINGLE oN
yOU aRE cA

sTUNTED, w
yOU aRE fL
yOU aRE lI
iN tHE cRI
tHAT dRIVE

cAN tHE sP
dRIP sUCH
hARDENED i
``````

We can also add more statements in the indented part of the code, and assign to other variables if we want. And we don’t have to `print` the `line` variable if we don’t want to—we can print some other expression entirely! For example, let’s say we wanted to print out the first four characters of each line, followed by the last four characters, storing those portions of the string in variables. Let’s try this:

``````import sys
for line in sys.stdin:
line = line.strip()
first_four = line[:4]
last_four = line[-4:]
print(first_four + last_four)
``````

Save this as `fours.py` and run it on `sea_rose.txt`:

``````SEA ROSE

Roseose,
marrals,
meaghin,
spareaf,

moreious
thanrose
singm --
you ift.

Stuneaf,
you and,
you fted
in tsand
thatind.

Can rose
dripance
hardeaf?
``````

EXERCISE: Write a Python program that prints out the length of each line in the input.

EXERCISE 2: Write a Python program that prints out each line of input twice.

EXERCISE 3: Write a Python program that uses the `.replace()` method to make replacements to the text on each line.

### Making decisions about lines

We’ve seen how to make a version of UNIX cat. Now let’s make a Python program called `simplegrep.py`, which is program that works a lot like UNIX grep.

``````import sys
for line in sys.stdin:
line = line.strip()
if "you" in line:
print(line)
``````

Run this with `sea_rose.txt` as input, and you’ll get the following results:

``````you are caught in the drift.
you are flung on the sand,
you are lifted
``````

The new thing in this program is the `if` statement. Here’s how `if` works. Write `if` followed by an expression that evaluates to `True` or `False`, followed by a colon. Any statements that are tabbed over under the `if` statement will only be executed if the expression evaluates to `True`. That’s why `simplegrep.py` above only printed out those three lines: it used the `in` operator to check to see if `you` was a substring of each line, and then only printed out the lines where that was the case.

You can put any expression that evaluates to `True` or `False` after the `if` keyword. Here’s a program that only prints out lines that are at least 20 characters long:

``````import sys
for line in sys.stdin:
line = line.strip()
if len(line) >= 20:
print(line)
``````

… producing the following output:

``````marred and with stint of petals,
meagre flower, thin,
you are caught in the drift.
Stunted, with small leaf,
you are flung on the sand,
that drives in the wind.
drip such acrid fragrance
``````

You can put multiple statements in the part of the code that follows the `if`, and the expression you print out doesn’t have to be `line`. Here’s a program that finds the first comma in each line, and then only prints out what follows the comma:

``````import sys
for line in sys.stdin:
line = line.strip()
space_position = line.find(" ")
if space_position != -1:
substring = line[space_position+1:]
print(substring)
``````

Run this with `sea_rose.txt` and you’ll get the following output:

``````ROSE
harsh rose,
and with stint of petals,
flower, thin,
of leaf,
precious
a wet rose
on a stem --
are caught in the drift.
with small leaf,
are flung on the sand,
are lifted
the crisp sand
drives in the wind.
the spice-rose
such acrid fragrance
in a leaf?
``````

EXERCISE: Write a Python program that prints only the lines in input that begin with a capital letter. (Hint: use string indexes and the `.isupper()` method.

You can use the `else` keyword to write code that will execute if the expression in an `if` statement evaluated to `False`. Here’s a modified version of the length-checking program above that prints the string “LONG” if the line is longer than 20 characters, and “SHORT” otherwise:

``````import sys
for line in sys.stdin:
line = line.strip()
if len(line) >= 20:
print("LONG")
else:
print("SHORT")
``````

Running this with `sea_rose.txt` yields the following output:

``````SHORT
SHORT
SHORT
LONG
LONG
SHORT
SHORT
SHORT
SHORT
SHORT
LONG
SHORT
LONG
LONG
SHORT
SHORT
LONG
SHORT
SHORT
LONG
SHORT
SHORT
``````

The `elif` keyword (short for “else if…”) allows you to write even more sophisticated tests: if the expression in the initial `if` clause evaluates to `False`, any following `elif` statement will have its expression evaluated; if that expression succeeds, the statements tabbed over beneath `elif` will be executed. If neither the `if` expression nor the `elif` expression evaluates to `True`, the statements beneath the `else` will run.

Here’s a program to illustrate, which prints different strings according to how many punctuation marks are in each line of input.

``````import sys
for line in sys.stdin:
line = line.strip()
punctuation = line.count(".") + line.count(",") + line.count("-") + line.count("?")
if punctuation >= 2:
print("many")
elif punctuation == 1:
print("only one")
else:
print("none :(")
``````

Here’s the output from `sea_rose.txt`:

``````none :(
none :(
many
only one
many
only one
none :(
none :(
none :(
many
only one
none :(
many
only one
none :(
none :(
only one
none :(
only one
none :(
only one
none :(
``````

You can actually have as many `elif` statements as you want, checking for many different conditional expressions.

## Conclusion

There’s much more to talk about here!

• Conditionals from “How to think like a computer scientist”: see especially the “Logical Operators” for information on how to combine expressions that evaluate as booleans into more sophisticated expressions.
• More Flow Control Tools from the Python tutorial
{"ft_lang_label":"__label__en","ft_lang_prob":0.8497901,"math_prob":0.79727465,"size":13964,"snap":"2019-13-2019-22","text_gpt3_token_len":3572,"char_repetition_ratio":0.13373925,"word_repetition_ratio":0.057918187,"special_character_ratio":0.2348181,"punctuation_ratio":0.12611991,"nsfw_num_words":0,"has_unicode_error":false,"math_prob_llama3":0.9539876,"pos_list":[0],"im_url_duplicate_count":[null],"WARC_HEADER":"{\"WARC-Type\":\"response\",\"WARC-Date\":\"2019-05-26T20:13:50Z\",\"WARC-Record-ID\":\"<urn:uuid:02c89591-369f-48c6-9235-aa62ddac0a77>\",\"Content-Length\":\"19395\",\"Content-Type\":\"application/http; msgtype=response\",\"WARC-Warcinfo-ID\":\"<urn:uuid:1f4d0056-5885-421b-88bd-355795eec678>\",\"WARC-Concurrent-To\":\"<urn:uuid:0b6128eb-dfc6-40bb-b19a-9f651e43f145>\",\"WARC-IP-Address\":\"207.38.94.47\",\"WARC-Target-URI\":\"http://rwet.decontextualize.com/book/writing-python-programs/\",\"WARC-Payload-Digest\":\"sha1:JIOVNJR4ZSKOAEGTSH274ERZXAR6OC7K\",\"WARC-Block-Digest\":\"sha1:J2WIQ7THIOOBKNZLID7YS7YW3KMVJWXI\",\"WARC-Identified-Payload-Type\":\"text/html\",\"warc_filename\":\"/cc_download/warc_2019/CC-MAIN-2019-22/CC-MAIN-2019-22_segments_1558232259452.84_warc_CC-MAIN-20190526185417-20190526211417-00467.warc.gz\"}"}