Site

Variables — Python Types and Variables

Tutorial 3.0  •  Python / Learn

3.0 What This Teaches

This tutorial covers how Python handles variables and types:

3.1 Dynamic Typing

Python is dynamically typed - you don't declare types, and the same name can hold different types at different times:
x = 42          # x holds an int
x = "hello"     # x now holds a str - perfectly valid
x = [1, 2, 3]   # x now holds a list
This differs from C# and Rust where a variable's type is fixed at compile time. In Python, types belong to objects, not names. The name x is just a label that can point to any object.

3.2 Built-in Types

TypeExampleNotes
int42, -7, 1_000_000Arbitrary precision; never overflows
float3.14, 1.5e1064-bit IEEE 754 double precision
boolTrue, FalseSubtype of int; True == 1, False == 0
str"hello", 'world'Immutable Unicode text
NoneTypeNoneThe absence of a value; like null in other languages
Use type(x) to check the type of any object. Use isinstance(x, int) to test whether an object is an instance of a type.

3.3 Names and Objects

Assignment binds a name to an object. Multiple names can point to the same object:
a = [1, 2, 3]
b = a           # b points to the same list object
b.append(4)
print(a)        # [1, 2, 3, 4] - a sees the change

a = [10, 20]    # a now points to a new list; b still points to original
print(b)        # [1, 2, 3, 4]
This is important for mutable types (lists, dicts). Immutable types (int, str, tuple) cannot be changed in place, so sharing them is safe.

3.4 None

None is the singleton that represents "no value". It is the default return value of functions that don't explicitly return anything. Test for it with is, not ==:
result = None

if result is None:
    print("no result yet")

# Functions return None implicitly
def do_nothing():
    pass

x = do_nothing()
print(x)        # None

3.5 Type Annotations

Python 3.5+ supports optional type annotations. They don't affect runtime behavior but help IDEs and tools like mypy catch type errors early:
name: str = "Alice"
age: int = 30
score: float = 88.5
active: bool = True

def greet(name: str, greeting: str = "Hello") -> str:
    return f"{greeting}, {name}!"
For nullable values (Python equivalent), use str | None (Python 3.10+) or Optional[str] from the typing module.

3.6 Multiple Assignment and Unpacking

a, b = 1, 2          # tuple unpacking
a, b = b, a          # swap without a temp variable
first, *rest = [1, 2, 3, 4]   # starred assignment
print(first)         # 1
print(rest)          # [2, 3, 4]

x = y = z = 0        # assign same value to multiple names
The swap idiom a, b = b, a is idiomatic Python. The right side is fully evaluated before any assignment happens.

3.7 Example - All Together

# Variables - demonstrates Python's type system.
count: int = 10
ratio: float = 3.14
flag: bool = True
name: str = "Alice"
missing = None

print(type(count), count)
print(type(ratio), ratio)
print(isinstance(flag, bool), isinstance(flag, int))  # True True (bool is int subtype)
print(name.upper())
print(missing is None)

x, y = 3, 4
x, y = y, x          # swap
print(f"x={x}, y={y}")
Expected output:
<class 'int'> 10
<class 'float'> 3.14
True True
ALICE
True
x=4, y=3

3.8 Exercise

Exercise
  • Assign an int, float, str, bool, and None to separate variables. Print each with type().
  • Try reassigning the same name to each type in turn - observe that Python accepts it without error.
  • Use tuple unpacking to swap two values in a single line. Confirm the swap by printing before and after.

3.9 Common Mistakes

Using == to compare with None

x = None
if x == None:   # works but wrong style
    pass
if x is None:   # correct - identity check, not equality
    pass
is None tests identity (same object in memory). == None tests equality and can be overridden by custom __eq__ methods. Always use is None.

Integer division vs float division

print(7 / 2)    # 3.5  (true division)
print(7 // 2)   # 3    (floor division)
print(7 % 2)    # 1    (modulo)
In Python 3, / always produces a float. Use // for integer (floor) division.

Mutating a shared object unintentionally

Assigning a list to two names does not copy it. Both names point to the same object. Use b = a.copy() or b = list(a) to get an independent copy.

3.10 Key Terms

TermMeaning
dynamic typingTypes belong to objects, not names; type can change at runtime
intArbitrary-precision integer; no overflow in Python
float64-bit IEEE 754 floating-point number
boolTrue or False; a subtype of int
NoneSingleton representing the absence of a value
type annotationOptional hint written as name: type; checked by mypy not Python
isinstance()Tests if an object is an instance of a type or its subtype
tuple unpackingAssigning multiple names from a tuple in one statement