Python Expressions in IDLE

Play with IDLE

In the language Python, you write a plus sign to tell the computer to add two numbers. To try this, launch IDLE. In response to the brown >>> prompt in IDLE’s “Python 3.8.0 Shell” window, type the expression
10 + 20
(with no space in front of the 10) and press the return or enter key. The value of the expression 10 + 20 (namely, 30) will be output in blue. You can press control-p to go back up to your previous line of input; control-n to come down to your next line.

Python 3.8.0 (v3.8.0:fa919fdf25, Oct 14 2019, 10:23:27)
[Clang 6.0 (clang-600.0.57)] on darwin
Type "help", "copyright", "credits" or "license()" for more information.
>>> 10 + 20
30

>>>

Add, subtract, multiply, and divide

The plus, minus, times, and divide symbols are called operators. We use asterisk instead of x for multiplication because x will be used as the name of a variable. The numbers on which we perform the arithmetic are called the operands of the operator.

>>> 10 + 20
30

>>> 10 - 20
-10

>>> 10 * 20
200

>>> 10 / 20
0.5

Two problems with division

If your Python script tells the computer to divide by zero, there will be blood. The computer will rebel and stop executing the script. (The ZeroDivisionError is an example of an exception.)

>>> 10 / 0
Traceback (most recent call last):
  File "<pyshell#6>", line 1, in <module>
    10 / 0
ZeroDivisionError: division by zero

Division with a double slash // chops the quotient to an integer (whole number). Since its fraction has been chopped off, we say that the quotient has been truncated. The // truncates the quotient towards negative infinity, not towards zero. No space between the two slashes.

>>> 9 / 2
4.5

>>> 9 // 2
4

>>> -9 // 2
-5

As we just saw, the single slash division does not truncate in Python 3. But Python has changed. The single slash division truncated in Python 2. See Common Stumbling Blocks.

Remainder

The // operator tells the computer to perform a division and give you the quotient.
The % operator tells the computer to perform a division and give you the remainder.

>>> 37 / 5
7.4

>>> 37 // 5
7

>>> 37 % 5
2

The % operator can instantly tell you what kind of election happens in a given year.
2020 is a presidential election year.
2018 was a midterm election year.
2017 was an off-year election year.

>>> 2020 / 4
505.0

>>> 2020 // 4
505

>>> 20202 % 4
0

>>> 2018 % 4
2

>>> 2017 % 4
1

Here’s an example that uses // and % together. 267 minutes is 4.45 hours, but people would rather think of it as 4 hours and 27 minutes. See why you’d want to use // and % instead of plain old /?

>>> 267 / 60
4.45

>>> 267 // 60
4

>>> 267 % 60
27

Exponentiation (raising to a power)

Let’s say you get 4% interest, compounded annually. After 20 years, your original principal will be multiplied by approximately 2.191123143033421. For example, if you started with $100,000.00, you would end up with $219,112.31 because

$100,000.00 × 1.04 × 1.04 × 1.04 × 1.04 × 1.04 × 1.04 × 1.04 × 1.04 × 1.04 × 1.04 × 1.04 × 1.04 × 1.04 × 1.04 × 1.04 × 1.04 × 1.04 × 1.04 × 1.04 × 1.04
= $100,000.00 × 1.0420
≅ $219,112.31

No space between the two asterisks.

>>> 2 * 2 * 2 * 2 * 2
32

>>> 2 ** 5
32

>>> 1.04 ** 20
2.191123143033421

>>> 100_000.00 * 1.04 ** 20
219112.31430334208

Operator precedence

In the following expression 1 + 2 * 3, the two operators + and * are both adjacent to, and therefore competing to sink their teeth into, the same operand, namely the hapless 2. When this happens, the operator with the higher precedence goes first. In this case, it’s the *.

>>> 1 + 2 * 3
7

You can make the + go first with parentheses. The operators inside the parentheses are always executed before the operators outside the parentheses.

>>> (1 + 2) * 3
9

This table lists all the Python operators in order of precedence, with the operators of highest precedence at the bottom. For example, multiplication has higher precedence than addition, so multiplication appears lower in the table.

We have already seen two examples that depend on operator precedence. Here they are again. In the first example, the two operators * and ** are adjacent to, and competing to sink their teeth into, the operand 1.04. (The ** wins.) In the second example, the two operators - and // are adjacent to, and competing to sink their teeth into, the operand 9. (The - wins.)

>>> 100_000.00 * 1.04 ** 20
219112.31430334208

>>> -9 // 2
-5

>>> -(9 // 2)
-4

Operator associativity

In the following example, the two subtraction operators - and - are adjacent to, and competing to sink their teeth into, the operand 2. But operator precedence can’t tell us which one goes first, because the two operators have the same precedence. (In fact, they’re the same operator.) In this case, we rely on operator associativity. Every Python operator (except **) has left-to-right associativity, so the minus sign on the left goes first.

>>> 1 - 2 - 3
-4

>>> 1 - (2 - 3)
2

Exponentiation has right-to-left associativity, so the ** on the right goes first:

>>> 2 ** 3 ** 2
512

>>> (2 ** 3) ** 2
64

The comparison operators

The result of a comparison is not a number. The result of a comparison is either True or False. No space between the two equal signs. The number 10 is a literal.

>>> 10 + 20
30

>>> 10 < 20
True

>>> 10 > 20
False

>>> 10 == 10
True

>>> 10 = 20
SyntaxError: can't assign to literal

Call a function

A Python script can be divided into sections called functions. For the time being (until we get to lambda functions), each function has a name. For example, someone has already written a function named round for us. We say that this function is built into the language.

To use a function, we often have to feed it some information to chew on. This information is called the argument of the function, and is written in parentheses after the function’s name. The value that the function gives back to us (or returns to us) is called the return value of the function.

>>> round(19.95)
20

>>> round(100_000.00 * 1.04 ** 20)
219112

>>> help(round)
Help on built-in function round in module builtins:

round(number, ndigits=None)
    Round a number to a given precision in decimal digits.

    The return value is an integer if ndigits is omitted or None.  Otherwise
    the return value has the same type as the number.  ndigits may be negative.

Some functions will accept (or demand) more than one argument. In that case, write all the arguments in the parentheses, separated by commas. Put a space after each comma because we put a space after each comma in English. For example, the round function will accept a second argument telling it how many digits to the right of the decimal point we want to round to. To round money to the nearest cent, this argument must be 2.

>>> 5 / 3
1.6666666666666667

>>> round(5 / 3)
2

>>> round(5 / 3, 2)
1.67

>>> round(100_000.00 * 1.04 ** 20, 2)
219112.31

>>> round(100_000.00 * 1.04 ** 20, -3)
219000.0

An amount of money should be formatted with exactly two digits the right of the decimal point. Python has three ways of formatting. The first way is the oldest; the third way is the newest. The f in .2f stands for “float”; see the Format Specification Mini-Language.

>>> "%.2f" % round(100_000.00 * 1.04 ** 20, -3)
'219000.00'

>>> "{:.2f}".format(round(100_000.00 * 1.04 ** 20, -3))
'219000.00'

>>> f"{round(100_000.00 * 1.04 ** 20, -3):.2f}"
'219000.00'

Call a function that has a last name

How many years would it take for your money to double at 4% interest, compounded annually? The full name of the function that answers this question is math.log. log is the first name of the function; math is the last name of the function. In the language Python, we write the last name on the left, the first name on the right, and a dot in between them. Thus, math.log. Like the round function, math.log can accept two arguments.

Functions that are built into the language (such as round) have no last name. Functions that are not built into the language (such as log) do have a last name, in this case math. Before we can use a function that is not built-in, we must import its family into the language as guests or immigrants. These families have names such as math or random.

In Python, a family is called a module. For the time being, you can think of a module as a family of functions that share the same last name: math.log, math.sqrt, math.sin, etc. (To see where the math module is located on your disk, we will print sys.modules["math"].)

>>> import math

>>> math.log(32, 2)
5.0

>>> math.log(2, 1.04)
17.672987685129698

>>> round(math.log(2, 1.04))
18

>>> import maath
Traceback (most recent call last):
  File "<pyshell#10>", line 1, in <module>
    import maath
ModuleNotFoundError: No module named 'maath'

String addition and string multiplication

In Python, a series of characters is called a string of characters. Write quotes around the string, either a pair of single quotes or a pair of double quotes. Here are three examples of strings:

"ha"
"Hello"
"Miss Moneypenny says that 007 has arrived."
>>> "ha" + "ha"
'haha'

>>> 3 * "ho"
'hohoho'

>>> 3 + "ho"
Traceback (most recent call last):
  File "<pyshell#17>", line 1, in <module>
    3 + "ho"
TypeError: unsupported operand type(s) for +: 'int' and 'str'

>>> len("Hello")
5

>>> len(3 * "ho")
6

A variable

A variable is a container which contains a value. For example, there’s a variable named pi. The value contained by this variable is the number π, and the variable belongs to the module math.

We’ve already seen this dot operator in expressions such as math.log or math.sqrt. Remember how the function log belonged to math? Well, in the same way, the variable pi belongs to math. To the right of the dot, you write the thing that belongs. To the left of the dot, you write the thing that it belongs to.

>>> math.pi
3.141592653589793

>>> import string

>>> string.ascii_uppercase
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

The expression 10 + 20 + 30 is made out of three subexpressions and two operators. So is the expression string.ascii_uppercase.__class__. In that expression,
string is a module,
ascii_uppercase is a variable belonging to the module string, and
__class__ is an attribute belonging to the variable string.ascii_uppercase.

>>> 10 + 20 + 30
60

>>> string.ascii_uppercase.__class__
<class 'str'>

Data type

Every expression has a value. For example, the value of our first expression 10 + 20 was 30, and the value of the expression math.pi was 3.141592653589793. There are many types of values: integer (whole number), floating point number, string of characters, etc. These types of values are called data types.

The simplest cases are easy to recognize. A value of type float is written as a number with a decimal point. A value of type int is written as a number without a decimal point. And a value of type string is written surrounded by a pair of quotes, either 'singles' or "doubles".

In case you can’t recognize the type of the value of an expression, the built-in function type will tell you which data type it is. The data type bool is named after George Boole.

>>> type(10 + 20)
<class 'int'>

>>> type(10)
<class 'int'>

>>> type(10.5)
<class 'float'>

>>> type(10.0)
<class 'float'>

>>> type(math.pi)
<class 'float'>

>>> type("hello")
<class 'str'>

>>> type("10")
<class 'str'>

>>> type(2 + 3j)
<class 'complex'>

>>> type(10 < 20)
<class 'bool'>

Purebreds vs. hybrids

If you combine two expressions whose values are of type int, the resulting expression has a value of type int:

>>> type(10 + 20)
<class 'int'>

If you combine two expressions whose values are of type float, the resulting expression has a value of type float:

>>> type(10.0 + 20.0)
<class 'float'>

And a hybrid results in a float:

>>> type(10.0 + 20)
<class 'float'>

>>> type(100_000.00 * 1.04 ** 20)
<class 'float'>

Warning: there are some values that cannot be stored in a float. Here’s the smallest one that is a positive whole number:

>>> 2.0 ** 53
9007199254740992.0

>>> 2.0 ** 53 + 1
9007199254740992.0

Type conversion

The type conversion functions int, float, str, bool, etc., take an expression and create a new value of a different type. Note that int truncates a float value towards zero, but round breaks a tie by rounding to an even integer. To break ties by rounding up, add .5 and then apply int to the sum.

>>> int(3.0)
3

>>> int(3.5)
3

>>> round(3.5)
4

>>> round(4.5)
4

>>> int(3.5 + .5)
4

>>> int("12345")
12345

>>> int("hello")
Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    int("hello")
ValueError: invalid literal for int() with base 10: 'hello'

>>> float("3.5")
3.5

>>> str(3.5)
'3.5'

>>> str(3) + "ho"
'3ho'

>>> len(str(12345))
5

>>> import math
>>> 1 + math.floor(math.log(12345, 10))
5

Why would we want to convert a string to an integer? The first example is coming up in Standard input. And we’ll convert an integer to a string in Flag.

Exceptions we’ve raised today

  1. ModuleNotFoundError: import maath
  2. SyntaxError: 10 = 20
  3. TypeError: 3 + "ho"
  4. ValueError: int("hello")
  5. ZeroDivisionError: 10 / 0

A function that accepts no arguments

To quit IDLE,

>>> quit()
Your program is still running!
Do you want to kill it?
OK