Week 2: Notes

more about Visual Studio Code

Notice that Visual Studio Code will report errors and warnings in your Python code. In the lower left corner of the window, you'll see a count of errors and warnings. For example, there are 4 errors and 2 warnings indicated here:

To see more about these errors, click the error or warning count in the lower left corner. Now the Problems pane will appear at the bottom of the window, showing detailed information about each error or warning:

You can click on any error in the list to highlight the corresponding editor line.

You'll need to fix errors to be able to run your program. I recommend that you also always fix all warnings in your code (not only in Python but also in any programming language).

making the IDE quieter

By default, Visual Studio Code enables numerous features that display extra information. For example:

If you find these features to be helpful, great. For me personally, many of them are distracting. I prefer an editor interface that doesn't display so much information, and that displays documentation only when I ask for it.

Fortunately, Visual Studio Code is highly customizable. If you want its editor to be quieter, you can use my preferred editor settings:

  1. In the lower left, click the gear icon.

  2. Select "Settings" to edit your settings.

  3. In the upper right, click the small icon with an arrow ("Open Settings (JSON)").

  4. The editor will display the file settings.json. Paste in these lines after the opening brace:

    "editor.autoClosingBrackets": "never",
    "editor.autoClosingQuotes": "never",
    "editor.autoSurround": "never",
    "editor.codeLens": false,
    "editor.guides.indentation": false,
    "editor.lightbulb.enabled": false,
    "editor.lineNumbers": "off",
    "editor.minimap.enabled": false,
    "editor.occurrencesHighlight": false,
    "editor.parameterHints.enabled": false,
    "editor.quickSuggestions": {
        "comments": "off",
        "strings": "off",
        "other": "off"
    },
    "editor.renderLineHighlight": "none",
    "editor.renderWhitespace": "none",
    "editor.selectionHighlight": false,
    "editor.suggestOnTriggerCharacters": false,
    "editor.suggestSelection": "first",
    "editor.tabCompletion": "on",
    "editor.unicodeHighlight.ambiguousCharacters": false,
    "editor.wordBasedSuggestions": false

With these settings, the editor will not display name autocompletions or function documentation automatically. If you're typing a name and want to see autocompletions, you can still get them by pressing Ctrl+Space. If you're typing a function call and want to see the function's documentation, you can still get it by pressing Ctrl+Shift+Space.

boolean operators

Python has boolean operators that can combine boolean values:

For example:

>>> True or False
True
>>> True and False
False
>>> not True
False
>>> not False
True

We often use these boolean operators to combine comparisons:

>>> 3 < 5 and 10 < 20
True
>>> not 10 <= 50
False

more assignment operators

As we know, the statement 'x = x + 2' means "add 2 to the variable x".

In fact, this type of operation is so common that Python has a special assignment operator += for this purpose, which lets us write this statement more succinctly:

>>> x = 10
>>> x = x + 2    # add 2 to x
>>> x
12
>>> x += 2       # add 2 to x
>>> x
14

The operators -=, *=, /=, //= and %= are similar. For example:

>>> y = 100
>>> y *= 20   # multiply y by 20
>>> y
2000

To increment a variable is to add 1 to it. Similarly, to decrement a variable is to subtract 1 from it:

x += 1          # increment x
y -= 1          # decrement y

more about ranges

In the last lecture, we saw that range(a, b) represents a sequence of integers from a up to but not including b. For example, the loop

for n in range(1, 10):
    print(n)

prints

1
2
3
4
5
6
7
8
9

range(a)

Alternatively you may call range() with only a single argument. range(a) means the same as range(0, a): it will produce the integers from 0 up to but not including a. For example, the loop

for n in range(5):
    print(n)

prints

0
1
2
3
4

Notice that for any non-negative integer n, range(n) produces n distinct numbers. And so a 'for' loop over range(0) will iterate 0 times, i.e. its body will never execute. This code produces no output:

for n in range(0):
    print(n)

range(a, b, c)

You may also call range() with three arguments. range(a, b, c) means the integers from a up to but not including b, stepping by c. For example, the loop

for n in range(4, 20, 2):
    print(n)

produces this output:

4
6
8
10
12
14
16
18

In other words, this loop generates numbers from 4 up to (but not including) 20, adding 2 at each step.

The step value may even be negative. The loop

for n in range(10, 0, -1):
    print(n)

will print

10
9
8
7
6
5
4
3
2
1

In general, if c > 0 then the loop

for n in range(a, b, c):
     (body) 

is equivalent to

n = a
while n < b:
     (body)     n += c

By studying this code, you should be able to see e.g. that range(10, 20, 30) will produce just a single value (10).

break

The 'break' statement will exit any kind of loop immediately. For example:

n = 1

while n <= 100:
    print(n)
    if n == 8:
        break
    n += 1

produces the output

$ py hello.py
1
2
3
4
5
6
7
8

When n is 8, the loop immediately exits.

'break' is sometimes convenient when we're looking for a certain value, and want to exit a loop when we find it. For example, suppose that we're looking for the first integer n such that the last 3 digits of n2 are 504 or 505. We could write

n = 0
while True:
    if 504 <= (n * n) % 1000 <= 505:
        print(n)
        break
    n += 1

Let's try it:

$ py find.py 
248

Here's another way to write the program, without 'break':

n = 0
while not (504 <= (n * n) % 1000 <= 505):
    n += 1
print(n)

You can decide which version you prefer.

continue

A related statement is 'continue', which aborts the current iteration of a loop and continues with the next iteration.

For example, the following loop adds up the sum of numbers from 1 to 100. However it uses the 'continue' statement to skip the number 28:

sum = 0

for i in range(1, 101):
    if i == 28:
        continue
    sum += i

print(sum)

In this particular loop, actually we could trivially replace 'continue' with a comparison using '!=':

for i in range(1, 101):
    if i != 28:
        sum += i

However 'continue' is sometimes convenient in situations where more code follows it, to avoid moving all that code into a nested block.

nested loops

It's common to nest one loop inside another. For example:

for x in 'abcd':        # outer loop
    for y in 'efg':     # inner loop
        print (x + y)

During each iteration of the outer loop, the inner loop will run in its entirety. This program will print

ae
af
ag
be
bf
bg
ce
cf
cg
de
df
dg

Note that the 'break' and 'continue' statements affect only the innermost loop that contains them. For example, let's add a 'break' to the previous program:

for x in 'abcd':        # outer loop
    for y in 'efg':     # inner loop
        print (x + y)
        if y == 'f':
            break

This version will produce this output:

ae
af
be
bf
ce
cf
de
df

The 'break' statement aborts the inner ('for y') loop, which causes the next iteration of the outer ('for x') loop to run.

math functions

Python includes a few math functions that are always available. abs(x) computes the absolute value of x, often denoted as |x|:

>>> abs(-5)
5

round() rounds a float to the nearest integer:

>>> round(2.3)
2

max() computes the maximum of two or more numbers:

>>> max(10, 5)
10
>>> max(10, 5, 20, 3)
20

Similarly, min() computes the minimum of two or more numbers:

>>> min(100, 77, 200, 88)
77

To get access to more math functions, import the 'math' module at the top of your program:

import math

Our Python Library Quick Reference lists various useful functions in this module, such as

To use any of these functions, write "math." followed by the name of the function. For example:

import math

print(math.sqrt(2))

prints

1.4142135623730951

random numbers

Our quick library reference also lists various functions that can generate random numbers. To use these, you must first write 'import random'. We will often use these as well.

A particularly useful function is random.randint(a, b), which returns a random integer n in the range a ≤ n ≤ b. Let's write a program that rolls a number of 6-sided dice, and prints their sum:

import random

n = int(input('How many dice? '))

sum = 0
for i in range(n):
    sum += random.randint(1, 6)

print('The total is', sum)

Let's run it:

$ py dice.py 
How many dice? 100
The total is 337

Here's something to consider: if we roll 100 dice and compute their sum, will it usually be less than or greater than 337?

standard input and output

We've already seen Python's input() and print() functions. input() reads a line from standard input. print() reads a line to standard output. By default standard input and output are the terminal, but we'll soon see that we can redirect them from or to a file.

At some point the input may reach its end. When the input comes from a terminal, we can signal the end of the input by typing ctrl+D (on Linux or macOS) or Ctrl+Z Enter (on Windows).

Let's write a program that reads numbers from standard input, one per line, until it ends. The program will print the sum of the numbers. We could try to use input() to read the numbers, however when the input ends input() will produce an error, which is inconvenient. As another approach, we can use the object sys.stdin, which represents a program's standard input. We can loop over sys.stdin using a 'for' statement. On each iteration, we'll receive the next input line as a string:

import sys
  
sum = 0
for line in sys.stdin:  # for each line of standard input
    n = int(line)       # convert string to integer
    sum += n
  
print('The sum is', sum)

Let's run the program, and give it some numbers as input:

$ python sum.py
3
4
5
^D

At the end we typed ^D (control D), meaning end of input. The program now prints

The sum is 12

redirecting standard input and output

When you run a program you may redirect its standard input to come from a file, and may also redirect standard output to a file.

Use the '<' character to redirect the input. For example, let's use a text editor to create a file test.in with these contents:

4
5
6

Now let's run the Python program frm the previous section, redirecting its input from test.in:

$ python sum.py < test.in
15

Similarly, you can use the > character to redirect a program's output. Let's run the program again, redirecting both the input and output:

$ python sum.py < test.in > test.out
$

The program ran, but produced no output on the terminal since its output was redirected. Let's look at the output it produced. You can view it in an editor. Alternatively, the 'cat' command (on Linux or macOS) will display the contents of a file:

$ cat test.out
15
$

Many of our homework assignments in our ReCodEx system will contain sample input(s) and sample output(s) for the program that you're supposed to write. You may want to place each sample input in a text file. Then you can run your program with its input redirected from each file in turn. That will be much more convenient than manually entering input data each time you run your program.

More about strings

Let's consider more string operations in Python. First, the len() function will give us the length of a string:

>>> len('zmrzlina')
8

We can use the [] operator to extract individual characters of a string s. The first character is s[0], the second is s[1], and so on:

>>> s = 'zmrzlina'
>>> s[0]
'z'
>>> s[1]
'm'

The number in the brackets (e.g. 0 or 1 above) is called an index. In Python, a negative index retrieves a character from the end of the string. For example, s[-1] is the last character, and s[-2] is the second to last:

>>> s[-1]
'a'
>>> s[-2]
'n'

Notice that strings in Python are immutable, meaning that they cannot change. So you cannot modify string characters:

>>> s = 'watermelon'
>>> s[2] = 'x'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

We'll learn about more string operations in next week's lecture.