Chapter 05: Values, Variables, and Types¶
1. Overview¶
Every Python program works with data. That data might be a number, a piece of text, a list of items, or the absence of a value entirely. Before you can write useful programs, you need to understand how Python stores and organizes data.
This chapter covers the foundational ideas: what a value is, how you attach a name to it, what types Python uses to categorize values, and how those types behave. These concepts appear in every Python program you will ever read or write, so getting them right early pays off immediately.
2. What You Will Learn¶
- The difference between a value and a variable
- How assignment works in Python
- What dynamic typing means and why it matters
- The built-in types:
int,float,complex,bool,str,NoneType, and a brief look atlist,tuple,dict, andset - How to check and convert types
- How variables are references, not containers
- The difference between mutable and immutable objects
- How to use
id(),is, and==correctly - Multiple assignment and unpacking
- Constants by convention
- Augmented assignment operators
- A preview of variable scope
3. Core Concepts¶
3.1 Values and Variables¶
A value is a piece of data. 42, "hello", 3.14, and True are all
values. They exist on their own, independent of any name.
A variable is a name that refers to a value. When you write:
you are telling Python: "create the integer object 42, and bind the name x
to it." The = sign is the assignment operator. It does not mean
"x equals 42" in the mathematical sense — it means "attach the label x to
the object 42."
You can think of a variable as a sticky note attached to an object. The note has a name on it, and it points to the object. Multiple notes can point to the same object, and you can move a note to a different object at any time.
Each line creates an object and binds a name to it.
3.2 Dynamic Typing¶
Python is dynamically typed. This means that variables do not have types — objects do. A variable is just a name, and you can rebind it to any object at any time, regardless of what it pointed to before.
x = 10 # x refers to an int
x = "hello" # x now refers to a str
x = [1, 2, 3] # x now refers to a list
This is different from statically typed languages like Java or C, where a
variable declared as int can only ever hold an integer.
The type belongs to the object, not the name. You can verify this with the
type() function.
Dynamic typing makes Python flexible and fast to write, but it also means you need to be aware of what type a variable currently holds, especially when passing values to functions.
3.3 The type() Function¶
type(value) returns the type of any object. The result is a type object,
not a string.
print(type(42)) # <class 'int'>
print(type(3.14)) # <class 'float'>
print(type("hello")) # <class 'str'>
print(type(True)) # <class 'bool'>
print(type(None)) # <class 'NoneType'>
print(type([1, 2, 3])) # <class 'list'>
You can compare the result of type() directly:
However, for type checking in real code, isinstance() is almost always
preferred. See section 3.10 for the reason.
3.4 Built-in Types¶
Python comes with a set of built-in types that cover the most common kinds of data. Here is an overview of each one.
int — Integers¶
An int is a whole number with no decimal point. Python integers have no
fixed size limit — they can be as large as your available memory allows.
The underscore separator (_) is purely visual. Python ignores it. You can
place it anywhere in a numeric literal to improve readability:
Python supports integer literals in four bases:
decimal = 255 # base 10 (default)
binary = 0b11111111 # base 2 — prefix 0b
octal = 0o377 # base 8 — prefix 0o
hexadecimal = 0xFF # base 16 — prefix 0x
# All four are the same value
print(decimal == binary == octal == hexadecimal) # True
float — Floating-Point Numbers¶
A float is a number with a decimal point. Python floats follow the IEEE 754
double-precision standard, which gives about 15–17 significant decimal digits
of precision.
pi = 3.14159
temperature = -12.5
scientific = 1.5e10 # 1.5 × 10^10 = 15000000000.0
small = 2.7e-4 # 2.7 × 10^-4 = 0.00027
Precision issues
Floats cannot represent every decimal number exactly. This is a fundamental property of binary floating-point arithmetic, not a Python bug.
When you need to compare floats, use math.isclose() instead of ==:
math.isclose() checks whether two values are close enough to be considered
equal, within a small relative and absolute tolerance. The default tolerances
work well for most practical cases.
For financial calculations where exact decimal arithmetic is required, use the
decimal module from the standard library instead of float.
complex — Complex Numbers¶
Python has built-in support for complex numbers. The imaginary part uses j
as its suffix.
Complex numbers are used in scientific and engineering applications. If you are not working in those domains, you can safely skip them for now.
bool — Booleans¶
A bool has exactly two values: True and False. Note the capital letters —
Python is case-sensitive.
bool is a subclass of int in Python. True behaves like 1 and False
behaves like 0 in arithmetic contexts:
print(True + True) # 2
print(True * 5) # 5
print(False + 1) # 1
print(int(True)) # 1
print(int(False)) # 0
This is occasionally useful (for example, counting how many items in a list satisfy a condition), but do not rely on it in code that needs to be readable.
Truthiness
Every Python object has a truth value. When used in a boolean context (like an
if statement), objects are evaluated as either truthy or falsy.
Falsy values:
- False
- None
- 0, 0.0, 0j
- "" (empty string)
- [], (), {}, set() (empty collections)
Everything else is truthy.
if "hello":
print("truthy") # this runs
if "":
print("truthy") # this does not run
if 0:
print("truthy") # this does not run
if 42:
print("truthy") # this runs
str — Strings¶
A str is a sequence of Unicode characters. Strings are created with single
quotes, double quotes, or triple quotes.
Strings are covered in depth in Chapter 07. For now, the key points are:
- Strings are immutable — you cannot change a character in place.
- You can concatenate strings with
+and repeat them with*. - You can check the length with
len().
language = "Python"
print(len(language)) # 6
print(language + " 3.10") # Python 3.10
print(language[0]) # P
NoneType — The Absence of a Value¶
None is Python's way of representing "no value" or "nothing here." It is the
only value of the NoneType type.
Common uses of None:
- A function that does not explicitly return a value returns
None. - A variable that has not been assigned a meaningful value yet.
- A default argument that signals "no argument was provided."
def greet(name=None):
if name is None:
print("Hello, stranger!")
else:
print(f"Hello, {name}!")
greet() # Hello, stranger!
greet("Alice") # Hello, Alice!
Always check for None using is None or is not None, not == None. The
reason is explained in section 3.9.
list, tuple, dict, set — Collections¶
Python has four built-in collection types. They are introduced briefly here and covered in full in Chapter 09.
# list — ordered, mutable sequence
fruits = ["apple", "banana", "cherry"]
# tuple — ordered, immutable sequence
coordinates = (10.5, 20.3)
# dict — key-value mapping
person = {"name": "Alice", "age": 30}
# set — unordered collection of unique values
unique_ids = {1, 2, 3, 4}
The key distinction for now: lists and dicts are mutable (you can change them after creation), while tuples are immutable (you cannot). This matters for how Python handles them in memory, which is covered in section 3.8.
3.5 Variable Naming Rules¶
Python has strict rules for variable names and strong conventions.
Rules (enforced by Python):
- Names can contain letters, digits, and underscores.
- Names cannot start with a digit.
- Names are case-sensitive:
count,Count, andCOUNTare three different variables. - Names cannot be Python keywords (
if,for,class,return, etc.).
# Valid names
user_name = "Alice"
_private = 42
count2 = 0
MAX_SIZE = 100
# Invalid names — these cause SyntaxError
# 2count = 0
# my-var = 5
# class = "math"
Conventions (PEP 8):
- Use
snake_casefor variables and functions:user_name,total_price. - Use
UPPER_SNAKE_CASEfor constants:MAX_RETRIES,PI. - Use
PascalCasefor class names:UserAccount,HttpClient. - Avoid single-letter names except for short loop counters (
i,j,k) or mathematical variables where the letter is conventional (x,y,n). - Choose descriptive names:
user_ageis better thanuaora.
3.6 Type Conversion (Casting)¶
You can convert a value from one type to another using the built-in conversion
functions: int(), float(), str(), bool(), list(), and tuple().
int()¶
Converts a value to an integer.
int("42") # 42 — string of digits
int(3.9) # 3 — truncates toward zero, does not round
int(True) # 1
int(False) # 0
int("0xFF", 16) # 255 — parse hex string with explicit base
int() raises ValueError if the string cannot be parsed as an integer:
int("hello") # ValueError: invalid literal for int() with base 10: 'hello'
int("3.14") # ValueError: invalid literal for int() with base 10: '3.14'
Note that int("3.14") fails even though float("3.14") would succeed. If
you have a float-formatted string and want an integer, convert in two steps:
float()¶
Converts a value to a float.
float() also raises ValueError on unparseable strings:
str()¶
Converts any value to its string representation.
str(42) # "42"
str(3.14) # "3.14"
str(True) # "True"
str(None) # "None"
str([1, 2, 3]) # "[1, 2, 3]"
str() never raises an error — every Python object has a string
representation.
bool()¶
Converts a value to True or False using Python's truthiness rules.
bool(1) # True
bool(0) # False
bool("hello") # True
bool("") # False
bool([1, 2]) # True
bool([]) # False
bool(None) # False
list() and tuple()¶
Convert an iterable to a list or tuple.
list("abc") # ['a', 'b', 'c']
list((1, 2, 3)) # [1, 2, 3]
tuple([1, 2, 3]) # (1, 2, 3)
tuple("hello") # ('h', 'e', 'l', 'l', 'o')
What cannot be converted¶
Not every conversion makes sense. Python will raise an error when a conversion is impossible:
int("hello") # ValueError
float("abc") # ValueError
int([1, 2, 3]) # TypeError: int() argument must be a string, a bytes-like
# object or a real number, not 'list'
Always handle potential ValueError or TypeError when converting user input
or data from external sources.
raw = input("Enter a number: ")
try:
number = int(raw)
print(f"You entered: {number}")
except ValueError:
print(f"'{raw}' is not a valid integer.")
3.7 isinstance() vs type()¶
There are two ways to check the type of an object. They behave differently and are used in different situations.
type(x) == SomeType checks for an exact type match. It returns False
if x is an instance of a subclass.
isinstance(x, SomeType) checks whether x is an instance of
SomeType or any subclass of it. This is almost always what you want.
print(type(True) == bool) # True
print(type(True) == int) # False — even though bool is a subclass of int
print(isinstance(True, bool)) # True
print(isinstance(True, int)) # True — because bool is a subclass of int
isinstance() also accepts a tuple of types to check against multiple types
at once:
x = 42
print(isinstance(x, (int, float))) # True — x is an int, which is in the tuple
y = "hello"
print(isinstance(y, (int, float))) # False
Rule of thumb: use isinstance() for type checks in real code. Use
type() when you specifically need to know the exact type and want to exclude
subclasses (which is rare).
3.8 Variables Are References¶
This is one of the most important concepts in Python, and it is the source of many beginner surprises.
In Python, a variable does not contain a value. It holds a reference to an
object. When you write x = 42, Python creates the integer object 42 in
memory and makes x point to it.
The id() Function¶
id(obj) returns the unique identity of an object — its memory address in
CPython. Two objects that are equal may or may not have the same identity.
x = 42
print(id(x)) # some integer, e.g. 140234567890
y = x
print(id(y)) # same integer — y points to the same object as x
When you assign y = x, you are not copying the value. You are making y
point to the same object that x already points to.
is vs ==¶
==checks value equality: do the two objects have the same value?ischecks identity: are the two names pointing to the exact same object in memory?
a = [1, 2, 3]
b = [1, 2, 3]
print(a == b) # True — same values
print(a is b) # False — different objects in memory
c = a
print(a is c) # True — c and a point to the same object
Use == when you want to compare values. Use is only when you want to check
object identity — the most common case being is None and is not None.
Never write if result == None. It works in practice, but is None is the
correct idiom and is enforced by linters.
Mutability vs Immutability¶
Whether a variable assignment creates a new object or modifies an existing one depends on whether the type is mutable or immutable.
Immutable types cannot be changed after creation. Any operation that appears to modify them actually creates a new object:
int,float,complex,boolstrtupleNoneType
x = "hello"
print(id(x)) # some address, e.g. 140000000001
x = x + " world"
print(id(x)) # different address — a new string object was created
Mutable types can be changed in place. Operations that modify them do not create a new object:
listdictset
numbers = [1, 2, 3]
print(id(numbers)) # some address, e.g. 140000000002
numbers.append(4)
print(id(numbers)) # same address — the same list object was modified
print(numbers) # [1, 2, 3, 4]
Why This Matters: Shared References¶
Because variables are references, two variables can point to the same mutable object. Modifying the object through one variable affects the other.
a = [1, 2, 3]
b = a # b points to the same list as a
b.append(4)
print(a) # [1, 2, 3, 4] — a was affected too!
print(a is b) # True
This is not a bug — it is intentional Python behavior. If you want an
independent copy of a list, use list() or the .copy() method:
a = [1, 2, 3]
b = list(a) # b is a new list with the same values
b.append(4)
print(a) # [1, 2, 3] — a is unchanged
print(a is b) # False
With immutable types, this is never an issue because you cannot modify the object in place anyway.
3.9 Multiple Assignment and Unpacking¶
Python lets you assign multiple variables in a single line.
Assigning the Same Value to Multiple Variables¶
All three names point to the same object. For immutable types like int, this
is perfectly safe. For mutable types, be careful:
If you want separate empty lists, use:
Tuple Unpacking¶
You can assign multiple variables from a sequence in one line:
The right side is a tuple (10, 20). Python unpacks it and assigns each value
to the corresponding name on the left.
This works with any iterable:
first, second, third = [1, 2, 3]
a, b, c = "abc"
# Swap two variables without a temporary variable
x, y = y, x
The number of names on the left must match the number of values on the right,
or Python raises a ValueError:
a, b = 1, 2, 3 # ValueError: too many values to unpack
a, b, c = 1, 2 # ValueError: not enough values to unpack
Extended Unpacking with *¶
The * operator collects remaining values into a list:
first, *rest = [1, 2, 3, 4, 5]
print(first) # 1
print(rest) # [2, 3, 4, 5]
*start, last = [1, 2, 3, 4, 5]
print(start) # [1, 2, 3, 4]
print(last) # 5
head, *middle, tail = [1, 2, 3, 4, 5]
print(head) # 1
print(middle) # [2, 3, 4]
print(tail) # 5
3.10 Constants¶
Python does not have a built-in mechanism for constants. There is no const
keyword. By convention, a name written in UPPER_SNAKE_CASE signals to other
programmers that the value should not be changed.
Nothing prevents you from reassigning these names — Python will not complain.
The convention is purely a communication tool. If you need enforced constants,
you can use typing.Final (covered in Chapter 19):
Type checkers like mypy will flag any attempt to reassign a Final variable,
but Python itself still allows it at runtime.
3.11 Augmented Assignment¶
Augmented assignment operators combine an arithmetic operation with assignment. They are shorthand for updating a variable based on its current value.
x = 10
x += 3 # equivalent to: x = x + 3 → 13
x -= 2 # equivalent to: x = x - 2 → 11
x *= 4 # equivalent to: x = x * 4 → 44
x /= 2 # equivalent to: x = x / 2 → 22.0 (always float)
x //= 3 # equivalent to: x = x // 3 → 7 (floor division)
x %= 3 # equivalent to: x = x % 3 → 1 (remainder)
x **= 4 # equivalent to: x = x ** 4 → 1 (exponentiation)
print(x) # 1
Note that /= always produces a float, even if both operands are integers:
Use //= if you want integer floor division.
Augmented assignment also works with strings and lists:
greeting = "Hello"
greeting += ", world!"
print(greeting) # Hello, world!
items = [1, 2]
items += [3, 4] # equivalent to items.extend([3, 4])
print(items) # [1, 2, 3, 4]
3.12 Variable Scope (Preview)¶
A variable's scope is the region of code where it is accessible. Python has four scope levels, often called LEGB:
- Local — inside the current function
- Enclosing — in an outer function (for nested functions)
- Global — at the top level of the module
- Built-in — names built into Python itself
For now, the key rule is: variables created inside a function are local to that function and cannot be accessed from outside it.
def calculate():
result = 42 # local variable
return result
print(result) # NameError: name 'result' is not defined
Variables created at the top level of a script are global and can be read
inside functions, but modifying them requires the global keyword.
Scope is covered in full in Chapter 10. For now, just be aware that where you define a variable determines where you can use it.
4. Practical Examples¶
Example 1: Working with Numeric Types¶
# Integer arithmetic
apples = 12
oranges = 7
total_fruit = apples + oranges
print(f"Total fruit: {total_fruit}") # Total fruit: 19
# Integer division vs float division
print(10 / 3) # 3.3333333333333335 (float division)
print(10 // 3) # 3 (floor division)
print(10 % 3) # 1 (remainder)
# Large integers — Python handles them natively
factorial_20 = 1
for i in range(1, 21):
factorial_20 *= i
print(factorial_20) # 2432902008176640000
# Float precision
import math
a = 0.1 + 0.2
b = 0.3
print(a == b) # False
print(math.isclose(a, b)) # True
print(f"a = {a:.20f}") # a = 0.30000000000000004441
print(f"b = {b:.20f}") # b = 0.29999999999999998890
Example 2: Type Checking and Conversion¶
def describe_value(value):
"""Print the value, its type, and whether it is truthy."""
print(f"Value: {value!r}")
print(f"Type: {type(value).__name__}")
print(f"Truthy: {bool(value)}")
print()
describe_value(42)
describe_value(0)
describe_value("hello")
describe_value("")
describe_value([1, 2, 3])
describe_value([])
describe_value(None)
Output:
Value: 42
Type: int
Truthy: True
Value: 0
Type: int
Truthy: False
Value: 'hello'
Type: str
Truthy: True
Value: ''
Type: str
Truthy: False
Value: [1, 2, 3]
Type: list
Truthy: True
Value: []
Type: list
Truthy: False
Value: None
Type: NoneType
Truthy: False
Example 3: Safe Type Conversion from User Input¶
def get_integer(prompt: str) -> int | None:
"""
Ask the user for an integer. Return the integer if valid,
or None if the input cannot be converted.
"""
raw = input(prompt)
try:
return int(raw)
except ValueError:
print(f"Error: '{raw}' is not a valid integer.")
return None
age = get_integer("Enter your age: ")
if age is not None:
print(f"In 10 years you will be {age + 10}.")
Example 4: Mutability in Practice¶
# Immutable: strings
original = "hello"
modified = original.upper()
print(original) # hello — unchanged
print(modified) # HELLO — new object
# Mutable: lists
numbers = [3, 1, 4, 1, 5]
numbers.sort()
print(numbers) # [1, 1, 3, 4, 5] — modified in place
# Shared reference trap
list_a = [1, 2, 3]
list_b = list_a # same object
list_b.append(99)
print(list_a) # [1, 2, 3, 99] — affected!
# Correct way to copy
list_c = list_a.copy() # independent copy
list_c.append(100)
print(list_a) # [1, 2, 3, 99] — not affected
print(list_c) # [1, 2, 3, 99, 100]
Example 5: Multiple Assignment and Unpacking¶
# Swap without a temporary variable
x = 10
y = 20
x, y = y, x
print(x, y) # 20 10
# Unpack a function return value
def min_max(numbers):
return min(numbers), max(numbers)
low, high = min_max([4, 1, 7, 2, 9, 3])
print(f"Min: {low}, Max: {high}") # Min: 1, Max: 9
# Extended unpacking
scores = [95, 88, 72, 65, 50]
best, *rest = scores
print(f"Best score: {best}") # Best score: 95
print(f"Other scores: {rest}") # Other scores: [88, 72, 65, 50]
# Ignore values with _
first, _, third = (1, 2, 3)
print(first, third) # 1 3
Example 6: Constants and Augmented Assignment¶
# Constants by convention
MAX_RETRIES = 3
BASE_URL = "https://api.example.com"
TIMEOUT_SECONDS = 30
# Augmented assignment in a loop
total = 0
for value in [10, 20, 30, 40, 50]:
total += value
print(f"Total: {total}") # Total: 150
# Building a string incrementally
report = "Report:\n"
report += f" Items processed: {len([10, 20, 30])}\n"
report += f" Total: {sum([10, 20, 30])}\n"
print(report)
Output:
Example 7: Using id() to Observe Object Identity¶
# Small integers are cached by CPython
a = 100
b = 100
print(a is b) # True — CPython caches small ints (-5 to 256)
a = 1000
b = 1000
print(a is b) # False — large ints are not cached (implementation detail)
# Strings may or may not be interned
s1 = "hello"
s2 = "hello"
print(s1 is s2) # True — CPython interns short strings (implementation detail)
# Never rely on is for value comparison
# Always use == for values, is only for identity (None, True, False)
print(s1 == s2) # True — always correct for value comparison
Note: The behavior of
iswith integers and strings is an implementation detail of CPython. Do not write code that depends on it. Use==for value comparisons andisonly forNone,True, andFalse.
5. Common Mistakes¶
Mistake 1: Using == to Check for None¶
is None is the correct idiom. == None works in most cases but can produce
unexpected results if an object defines a custom __eq__ method that returns
something unexpected when compared to None. Linters like flake8 and
ruff will flag == None as a style error.
Mistake 2: Confusing = and ==¶
# This is assignment — it always succeeds
x = 5
# This is comparison — it returns True or False
x == 5
Using = inside a condition is a SyntaxError in Python (unlike C or Java,
where it is a common bug):
Python 3.8 introduced the walrus operator := for assignment inside
expressions, but that is a different, intentional feature.
Mistake 3: Assuming int() Rounds¶
int() does not round — it truncates toward zero.
If you want rounding, use round():
print(round(3.9)) # 4
print(round(-3.9)) # -4
print(round(3.5)) # 4 — rounds to even (banker's rounding)
print(round(2.5)) # 2 — rounds to even
Mistake 4: Mutating a Shared Reference¶
# Wrong — both variables point to the same list
defaults = [1, 2, 3]
my_list = defaults
my_list.append(4)
print(defaults) # [1, 2, 3, 4] — unintended mutation
# Correct — make an explicit copy
my_list = defaults.copy()
my_list.append(4)
print(defaults) # [1, 2, 3] — unchanged
This mistake is especially common when using a mutable object as a default function argument. That specific case is covered in Chapter 10.
Mistake 5: Comparing Types with type() Instead of isinstance()¶
# Wrong — misses subclasses
def process(value):
if type(value) == int:
print("integer")
process(True) # prints nothing — bool is a subclass of int, not int itself
# Correct
def process(value):
if isinstance(value, int):
print("integer")
process(True) # prints "integer"
Mistake 6: Expecting 0.1 + 0.2 == 0.3¶
# This is False — a common beginner surprise
print(0.1 + 0.2 == 0.3) # False
# Use math.isclose() for float comparisons
import math
print(math.isclose(0.1 + 0.2, 0.3)) # True
Mistake 7: Reassigning a Constant¶
PI = 3.14159
# Python will not stop you from doing this
PI = 3 # no error, but this is wrong by convention
# If you need enforcement, use typing.Final
from typing import Final
PI: Final = 3.14159
# A type checker will now flag any reassignment of PI
Mistake 8: Unpacking with the Wrong Number of Values¶
a, b = 1, 2, 3 # ValueError: too many values to unpack (expected 2)
a, b, c = 1, 2 # ValueError: not enough values to unpack (expected 3)
If you are not sure how many values a sequence contains, use extended
unpacking with * to collect the extras:
6. Practice Tasks¶
Work through these tasks to reinforce the concepts in this chapter. Try each
one before looking at the solutions in
docs/solutions/05-values-variables-types.md.
Task 1: Type Explorer
Write a script that creates one variable of each of the following types:
int, float, bool, str, NoneType. For each variable, print:
- The value
- The type (using
type()) - Whether it is truthy (using
bool())
Expected output format:
Task 2: Safe Converter
Write a function safe_int(value) that:
- Accepts any value
- Returns the value converted to
intif the conversion succeeds - Returns
Noneif the conversion fails (catchesValueErrorandTypeError)
Test it with these inputs: "42", "3.14", "hello", True, None,
[1, 2].
Task 3: Integer Bases
Write a script that:
- Defines the number 255 using decimal, binary, octal, and hexadecimal literals.
- Prints all four variables and confirms they are equal.
- Converts the decimal 255 to its binary, octal, and hex string
representations using
bin(),oct(), andhex().
Task 4: Float Precision
Write a script that demonstrates the float precision problem:
- Compute
0.1 + 0.2and print the result. - Check if
0.1 + 0.2 == 0.3and print the result. - Use
math.isclose()to check the same comparison and print the result. - Print both values to 20 decimal places using an f-string format spec
(
:.20f) to show why they differ.
Task 5: Mutability Test
Write a script that:
- Creates a list
original = [1, 2, 3]. - Creates
alias = original(a reference, not a copy). - Creates
copy = original.copy()(an independent copy). - Appends
99toalias. - Prints
original,alias, andcopy. - Uses
isto confirm thatoriginalandaliasare the same object, and thatoriginalandcopyare not.
Task 6: Unpacking Practice
Given the list data = [10, 20, 30, 40, 50]:
- Unpack the first element into
firstand the rest intoremaining. - Unpack the last element into
lastand the rest intobeginning. - Unpack the first and last elements, collecting the middle into
middle. - Print all results.
Task 7: Augmented Assignment Counter
Write a script that simulates a simple score tracker:
- Start with
score = 0. - Add 10 points three times using
+=. - Subtract 5 points once using
-=. - Double the score using
*=. - Print the final score.
What is the expected final score?
Task 8: Constants Module
Create a small Python file called constants.py that defines at least five
constants relevant to a simple application of your choice (for example, a
quiz app, a unit converter, or a simple game). Use UPPER_SNAKE_CASE naming.
Then write a second script that imports and uses those constants.
Task 9: Identity vs Equality
Write a script that demonstrates the difference between is and ==:
- Create two lists with the same values. Show that
==returnsTruebutisreturnsFalse. - Create two variables pointing to the same list. Show that both
==andisreturnTrue. - Check
Noneusing both== Noneandis None. Show that both returnTruefor aNonevalue, but explain whyis Noneis preferred.
Task 10: Type Conversion Chain
Starting with the string " 42 " (note the surrounding spaces):
- Strip the whitespace using
.strip(). - Convert to
int. - Multiply by 2.
- Convert back to
str. - Concatenate with the string
" is the answer". - Print the final result.
This simulates a common pattern when processing user input or data from files.
7. Key Takeaways¶
-
A value is a piece of data. A variable is a name bound to a value using the assignment operator
=. -
Python is dynamically typed: variables have no type, objects do. You can rebind a name to any object at any time.
-
Use
type(x)to inspect the type of any object. Useisinstance(x, T)for type checks in real code — it handles subclasses correctly. -
Python's core built-in types are
int,float,complex,bool,str,NoneType,list,tuple,dict, andset. -
inthas no size limit in Python. Use0b,0o,0xprefixes for binary, octal, and hex literals. Use_as a visual separator in large numbers. -
floathas precision limits. Never use==to compare floats — usemath.isclose()instead. -
boolis a subclass ofint.True == 1andFalse == 0. Every Python object has a truth value. -
Noneis Python's null value. Always check for it withis Noneoris not None, never with== None. -
Use
int(),float(),str(),bool(),list(), andtuple()to convert between types. HandleValueErrorandTypeErrorwhen converting untrusted input. -
Variables are references to objects, not containers. Two variables can point to the same object.
-
Immutable types (
int,float,str,tuple,bool,None) cannot be changed in place. Mutable types (list,dict,set) can. -
Use
id()to inspect object identity. Useisto compare identity and==to compare values. Useisonly forNone,True, andFalsein production code. -
Python supports multiple assignment (
x = y = 0), tuple unpacking (a, b = 1, 2), and extended unpacking (first, *rest = items). -
Constants are a naming convention (
UPPER_SNAKE_CASE). Python does not enforce them, buttyping.Finallets type checkers flag reassignments. -
Augmented assignment operators (
+=,-=,*=,/=,//=,%=,**=) update a variable based on its current value. Note that/=always produces afloat. -
Variable scope determines where a name is accessible. Variables defined inside a function are local to that function. Full scope rules are covered in Chapter 10.
Further Reading¶
What's Next¶
Ready to continue? Head to the next chapter: Operators, Expressions, and Input.
→ Chapter 06 — Operators, Expressions, and Input
See also: - Exercise - Solution - Cheatsheet