s 1.2 Data, Expressions & Variables
HPy · Unit 1 Review

1.2 Data, Expressions
& Variables

Basic Programming Constructs · a running review, since you have done most of this before

FRQ · Warm-Up

What is a variable?

In your own words: what is a variable, and what does it do?

1.2.3 Variables

A variable is a name attached to a value

x
5
Try This

Reading a variable

Once a variable is assigned, using its name anywhere in the code gets you its currently assigned value, the most recent value the variable was given.

main.py
1x = 5
2print(x)
3print(x + 1)

Line 1 assigns 5 to x. Lines 2 and 3 both read it, they do not change it.

x
5
console
5 6
Not Like Math Class

Variables can be reassigned

main.py
1x = 5
2print(x)
3x = True
4print(x)

x starts as an int, then gets reassigned to a bool. Python lets a variable hold any type of data, and a new assignment always overwrites what was there before.

x
5 True
Reassigned!
console
5 True
Naming Rules

Legal variable names

  • Must start with a letter, never a digit.
  • After that, only letters, digits, and underscores (_) are allowed.
  • No spaces, no punctuation, and Python's reserved words (like print or True) are off limits as names.
  • camelCase capitalizes each word after the first; snake_case separates words with underscores instead. We'll write camelCase, but you should be able to read either.
camelCase· used in this course
numberOfRabbits = 40
thisIsFun = True
snake_case· you'll see this too
number_of_rabbits = 40
this_is_fun = True
MCQ

What happens if a name is illegal?

main.py
4thGradeMath = 'arithmetic'  # illegal: starts with a digit

What kind of error does Python display when it runs this code?

  • A IllegalVariableNameError
  • B SyntaxError
  • C UnknownError
  • D SemanticError
Errors

What is a SyntaxError?

A SyntaxError means Python could not understand the grammar of your code, before it ever starts running. It is like a sentence with its words out of order: the reader stops at the mistake and cannot continue until it is fixed.

This is different from a mistake in your logic. A SyntaxError is caught immediately, before a single line executes.
terminal
File "main.py", line 1
  4thGradeMath = 'arithmetic'
  ^
SyntaxError: invalid decimal literal
Activity

Trace the Boxes

Each box on the next slide is a variable. Read the highlighted line of code, work out what value it assigns, then drag (or click, then click the box) the matching value chip into the right box. Some chips are decoys, values you'd get from a common misreading, so evaluate the line before you place a chip.

Activity · Trace the Boxes
game.py

All boxes traced correctly. That's assignment: a name always holds its most recently assigned value.

Recap

What a variable really is

  • Assignment (=) stores a value in a named box; reading the name later gets whatever was most recently assigned.
  • A variable can be reassigned at any time, even to a value of a different type.
  • Legal names start with a letter and contain only letters, digits, and underscores; this course writes them in camelCase.
1.2.2 Constants

Values that aren't meant to change

A constant is a name attached to a value, just like a variable, except the value is not meant to change while the program runs.

Python itself comes with a few names built in, so you never assign them yourself. True and False are logical values, and None stands for "no value," used whenever nothing else makes sense.

True
False
None
Try This

Built-in math constants

The math module packages up useful constants, like math.pi, so you never have to type them out by hand. import math is what unlocks them.

main.py
1import math
2print(math.pi) # prints pi
3print(math.e) # prints e
Text after # is a comment. Python ignores it completely, comments exist to help you (and other humans), not the computer.
console
3.141592653589793 2.718281828459045
MCQ

Do comments change how code runs?

What happens if you delete the comments from the previous example and then run it?

  • A Nothing changes. The code runs exactly the same with and without comments.
  • B The code runs, but it prints out different values.
  • C The code crashes without the comments.
See For Yourself

Run it without the comments

Here is the same program with the comments stripped out. Run it and confirm the output is identical, comments never change what the code does.

main.py
import math
print(math.pi)
print(math.e)
Constants You Define

Naming your own constants

  • Python has no const or final keyword; nothing stops you from reassigning any name.
  • By convention, a value meant to stay fixed gets a name in UPPER_SNAKE_CASE: all caps, words separated by underscores.
  • It is a signal to other programmers ("don't change this"), not a rule Python enforces.
UPPER_SNAKE_CASE· your own constants
MAX_SPEED = 120
GRAVITY = 9.8
camelCase· regular variables, expected to change
currentSpeed = 0

Nothing crashes if you reassign MAX_SPEED, the all-caps name is the only thing telling you (and Python) not to.

Recap

Constants: values that shouldn't change

  • True, False, and None are built into Python; you never assign them yourself.
  • import math unlocks built-in constants like math.pi and math.e.
  • Anything after # is a comment: for humans, ignored by Python.
  • Python has no const keyword; UPPER_SNAKE_CASE is just a naming convention for your own constants.
1.2.1 Types

Every value has a type

Python sorts every value into a type: what kind of thing it is. type(123) reports it obscurely as <class 'int'>, you can just read that as int.

123 is an integer, in Python, it has the type int.

main.py
print(type(123))
console
<class 'int'>
→ read as int
Numeric Types

int vs float

  • Any number with a decimal point is a float, so 42.0 is a float, not an int.
  • Integers can have any number of digits; 78238723874327827348724783 is still just an int.
  • Python writes very large or very small floats in scientific notation: 4.1 × 1048 becomes 4.1e+48.
int· whole numbers
123
78238723874327827348724783
float· has a decimal point
4.56
42.0
4.1e+48
Non-Numeric Types

bool, str, NoneType

  • True and False are the only bool values, we already met these as constants.
  • A str holds text: single or double quotes both work, but the opening and closing quote must match. The empty string '' is still a string, just with length 0.
  • None is the one and only value of type NoneType.
bool
True
str
"abc"
NoneType
None
One More Thing

type is a type too

int is a type. But what is the type of int itself? Every Python type is a value, and every type's type is… type.

main.py
print(type(int))
console
<class 'type'>
MCQ

Quotes and decimal points change everything

main.py
print(type(0.))

What is type(0.)?

  • A int
  • B float
  • C str
main.py
print(type('0.'))

What is type('0.')?

  • A int
  • B float
  • C str
See For Yourself

Run both and compare

Run this side by side and check the two lines of output against your answers: 0. without quotes is a float, and '0.' inside quotes is a str.

main.py
print(type(0.))
print(type('0.'))
Activity

Sort by Type

Drag (or click, then click the bin) each value chip into the type it belongs to. A few pairs look alike: quotes make a string, a decimal point makes a float, so read each value carefully before you sort it.

Activity · Sort by Type

All 8 values sorted. Quotes make a string, a decimal point makes a float, and the rest come down to what the value actually is.

Recap

Types, at a glance

  • Every value has a type; type(x) tells you which one.
  • Numbers split into int (whole numbers) and float (has a decimal point, or written in scientific notation).
  • bool, str, and NoneType round out the core types we've met so far.
  • Quotes make a string; a decimal point makes a float, the two details worth double-checking.
1.2.4 Operators

Operators: symbols that compute

An operator is a symbol that performs some computation. + is the addition operator, so 2 + 3 is 5.

  • Arithmetic operators do math: + - * / ** // %.
  • Comparison operators compare two values and return a bool.
  • Logical operators combine bool values: and or not.
  • Assignment operators, like +=, are a shorthand for updating a variable.
Arithmetic Operators

The standard four

  • * is the multiplication operator.
  • / is the division operator.
  • / always returns a float, so 6 / 2 is 3.0, not the int 3.
main.py
1print(6 + 2)
2print(6 - 2)
3print(6 * 2)
4print(6 / 2)
console
8 4 12 3.0
Arithmetic Operators

Three more to know

  • ** is exponentiation: 2 ** 3 is 2 to the 3rd power, 8.
  • // is floor division: regular division, then rounded down. 11 / 4 is 2.75, so 11 // 4 is 2.
  • % is remainder (or "modulo", or "mod"): the leftover after division. 14 % 5 is 4, since 14 divided by 5 leaves a remainder of 4.
main.py
1print(2 ** 3)
2print(11 // 4)
3print(14 % 5)
console
8 2 4
Errors

What is a runtime error?

A runtime error means Python understood your code just fine and started running it, but hit an operation partway through that it cannot actually perform. Dividing by 0 is a classic example: there is no answer, so Python raises a ZeroDivisionError and stops.

Everything before the crash already ran. Everything after it never will, the program has already stopped.
main.py
1print("before")
2print(1 / 0)
3print("after") # never runs
console
before
Traceback (most recent call last):
  File "main.py", line 2, in <module>
    print(1 / 0)
ZeroDivisionError: division by zero
Quick Check

Predict, then reveal

main.py
1print(129 % 10)
2print(129 // 10)
3print(14 % 1)
4print(14 % 15)
console
9 12 0 14
Common Use

Testing even or odd

Even numbers are divisible by 2, so if x is even, x % 2 is 0. If x % 2 is 1, then x is odd.

main.py
x = 7
print(x % 2)
console
1
→ 7 is odd
Comparison Operators

Comparing two values

Comparison operators compare two values and return a bool.

  • == equal to · != not equal to
  • < less than · <= less than or equal
  • > greater than · >= greater than or equal
A single = assigns a value. A double == compares two values. Mixing these up is a common bug.
main.py
1print(1 == 2)
2print(3 != 4)
3print(5 < 6)
4print(7 <= 8)
5print(9 >= 9)
6print(10 > 10)
console
False True True True True False
MCQ · Select All

Which lines print False?

  • A print(1 == 2)
  • B print(3 != 4)
  • C print(5 < 6)
  • D print(7 <= 8)
  • E print(9 >= 9)
  • F print(10 > 10)
Logical Operators

Combining bool values

  • and: true only if both sides are true.
  • or: true if either side (or both) is true.
  • not: flips a value, true becomes false and back.
main.py
1print(True and True)
2print(True and False)
3print(False or False)
4print(False or True)
5print(not False)
6print(True and not False)
console
True False False True True True
Combining Expressions

Comparisons plus logic

Comparison and logical operators combine to build bigger conditions. Work out each comparison first, then apply and, or, or not.

main.py
1x = 5
2y = 7
3print((3 < x) and (y < x))
4print((3 < x) or (y < x))
5print(not (x >= y - 2))
console
False · 3<x is True, y<x is False True · either side true is enough False · x >= y-2 is True, so not flips it
MCQ · Select All

Which lines print True?

Given x = 5 and y = 7:

  • A print((3 < x) and (y < x))
  • B print((3 < x) or (y < x))
  • C print(not (x >= y - 2))
Assignment Operators

The += shorthand

x += y is basically the same as x = x + y. It is mostly a convenience, but it is common, so you need to be comfortable reading it.

main.py
1x = 5
2x = x + 3
3print(x)
4y = 5
5y += 3
6print(y)
console
8 8
Assignment Operators

Every arithmetic operator has one

Besides +=, every arithmetic operator has a matching assignment operator. x -= y is the same as x = x - y, and so on.

+=
-=
*=
/=
//=
%=
**=
Quick Check

Predict, then reveal

b = 7
b /= 2
3.5
c = 7
c //= 2
3
d = 7
d %= 2
1
e = 7
e **= 2
49
Recap

Operators, at a glance

  • Arithmetic: / always returns a float, // floors the result, % gives the remainder.
  • Runtime errors: code that is written correctly can still crash while running, like dividing by 0.
  • Comparison: == compares, = assigns; do not confuse them.
  • Logical: and, or, and not combine and flip bool values.
  • Assignment: += and friends are shorthand for "update this variable using its current value."
1.2.5 More About Operators

A few more important details

Now that you know the operators themselves, here are a handful of details about how expressions actually behave, including a couple of common gotchas.

  • Assigning to more than one variable at once.
  • How types change what an operator does.
  • The order Python evaluates operators in.
  • Why floats can be sneaky, and what an expression even is.
Parallel Assignment

Assigning more than one variable

Parallel (or "tuple") assignment lets you assign several variables on one line. The names on the left line up, in order, with the values on the right.

You never have to use it, one variable per line always works, but it can be convenient.

main.py
1x, y = 2, 3
2print(x)
3print(y)
console
2 3
A Classic Bug

Swapping the wrong way

Say x = 2 and y = 3, and we want to swap them. This does not work:

main.py
1x = y
2y = x
3print(x)
4print(y)

Once x = y runs, x's old value (2) is gone for good. There is nothing left to give y.

x
2 3
y
3 3
console
3 3
What happened to 2?!
Two Fixes

Swapping correctly

temp · a helper variable
temp = x
x = y
y = temp

temp briefly holds x's old value so it isn't lost.

parallel · one line
x, y = y, x

Both right-hand values are read before either assignment happens.

The key rule: in parallel assignment, Python computes every value on the right before assigning any of them to the names on the left.
See For Yourself

Try both swaps

Run the temp-variable version first. Then comment it out and try the one-line parallel swap instead. Both should print the same result.

Chained Operators

Chained assignment

To give the same value to multiple variables, you can chain assignments on one line.

x = y = 123 ** 45

This assigns 123 ** 45 to both x and y.

Chained Operators

Chained comparison

Comparison operators can chain too, instead of writing it out with and.

(0 < i) and (i <= j)
# is the same as:
0 < i <= j

Neither is required, but you should be able to read both.

Types Affect Semantics

+ means different things

The meaning of an operator can depend on the types of its values. For numbers, + adds. For strings, + concatenates, joins them end to end.

main.py
1print(2 + 3)
2print('a' + 'b')
console
5 'ab'
Types Affect Semantics

* is even trickier

  • Number * number: multiplies, as expected.
  • Number * string: repeats the string that many times.
  • String * string: causes an error. Python has no idea what that would mean.
main.py
1print(2 * 3)
2print('a' * 3)
3print('a' * 'b')
console
6 'aaa' TypeError
See For Yourself

Watch the error happen

Run this and read the error message for the last line. It names the exact types that don't get along, this is a very readable error once you know to look for it.

Precedence

What runs first

When an expression uses several operators, Python follows the same order you learned in math class.

  1. Parentheses ( ), always first.
  2. Exponentiation **.
  3. Multiplicative operators: * / // %.
  4. Additive operators: + -.

Within a level, Python works left to right, except **, which works right to left (rare to matter in practice).

Precedence

Tracing 1 + 2 * 3

1 + 2 * 3

Step 1: multiplication runs first, 2 * 36.

Step 2: 1 + 67.

MCQ

What is 5 - (4 + 8 % 3)?

Work from the inside out: parentheses, then %, then +, then -.

  • A -1
  • B 1
  • C 9
  • D -9
Floating-Point Gotcha

Floats are only approximate

Like most languages, Python's float values can be off by a tiny, almost invisible amount.

main.py
1print(0.1 + 0.1)
2print(0.1 + 0.2)
console
0.2 0.30000000000000004
See For Yourself

Never use == with floats

Run this. The second line prints False, even though 0.1 + 0.2 looks like it should equal 0.3.

Tiny rounding differences make == unreliable for floats. For now, just know the problem exists, later we'll meet a safer way to compare them.
Vocabulary

Expressions vs statements

An expression is anything that produces a value, anything that could go on the right-hand side of variable = expression. Literals, variables, function calls, and combinations of these with operators are all expressions.

A statement is a full action or command, like an assignment or a function definition.

Every expression is also a statement, but most statements are not expressions. That's why print(x), a function call and therefore an expression, can stand alone as its own line of code.
Multiline Expressions

Spanning multiple lines

You cannot simply break an expression across lines. Wrapping it in ( ) fixes that, and lets you format long expressions for clarity.

does not work
x = 12345 *
    67890
works
x = (12345 *
      67890)

Indent the continued line so it lines up just past the opening parenthesis.

MCQ

One step of 9 // 3 ** 2 ** 0

Remember: ** is right-to-left, so the rightmost ** goes first.

  • A 9 // 9 ** 0
  • B 3.0 ** 2 ** 0
  • C 3 ** 2 ** 0
  • D 9 // 3 ** 1
Errors

What is a logic error?

A logic error is the sneakiest kind. Python understands your code, runs it start to finish, and never crashes. It does exactly the math you wrote, it's just not the math you meant.

Sometimes, if you're lucky, a logic error surfaces later as a runtime error. Most of the time, you won't be so lucky, it will just quietly give you the wrong answer.
main.py
1a = 4
2b = 8
3average = a + b / 2
4print(average)
5items = 24
6groups = items / (average - 8)
7print(groups)
console
8.0
Traceback (most recent call last):
  File "main.py", line 6, in <module>
    groups = items / (average - 8)
ZeroDivisionError: float division by zero
a
4
b
8
average
8.0
items
24
groups

The average of 4 and 8 should be 6. But / runs before +, so this actually computes a + (b / 2). The fix is parentheses: (a + b) / 2.

Practice · Hand Trace

Trace it, don't guess

Predict each line before you reveal it. Hand-tracing catches logic errors that Python will never warn you about. It just does the math you told it to.

Lines 5 and 6 use the exact same numbers. The only difference is where the parentheses go, and that is the difference between a bug and a correct answer.
main.py
1print(3 + 2 * 5)
2print((3 + 2) * 5)
3a = 4
4b = 8
5print(a + b / 2)
6print((a + b) / 2)
console
13 25 8.0 6.0
Recap

Operators, the fine print

  • Parallel assignment reads every right-hand value before assigning any of them, which is exactly why x, y = y, x can swap two variables.
  • Types change meaning: + and * behave differently for numbers versus strings.
  • Precedence follows math class: parentheses, then **, then * / // %, then + -.
  • Logic errors never crash your program, they just give you the wrong answer. Hand-tracing your code line by line is how you catch them.
  • Floats are approximate, never compare them with ==.