Variables
Variables store values in named references. Python is dynamically typed: a variable can hold any type, and the type can change during execution. Understanding assignment, unpacking, and scope is essential for writing correct code.
Variable Assignment
A variable is created by assigning a value to a name. No explicit declaration is required.
x = 2
name = "Alice"
items = [2, 4, 6, 8]Naming rules: Names must start with a letter or underscore; the rest may be letters, digits, or underscores. Names are case-sensitive: count and Count are different.
Reassignment: A variable can be reassigned to a new value of any type.
x = 2
x = "two"
x = [2, 4]Multiple Assignment
Chained assignment: Several variables can be bound to the same value in one statement.
x = y = z = NoneAll three names refer to the same object. For immutable values (e.g. None, integers), this is safe. For mutable values (e.g. lists), all names share the same object; mutating one affects all.
a = b = c = []
a.append(2)
# b and c also see [2]Parallel assignment: Assign different values to multiple variables in one line.
a, b, c = 2, 4, 6The right-hand side is evaluated first, then values are assigned left to right. The number of names must match the number of values.
Unpacking
Tuple or list unpacking: Assign elements of a sequence to multiple variables.
data = ["Apple", 2, 4.2]
x, y, z = data
# x = "Apple", y = 2, z = 4.2Equivalent to: x = data[0], y = data[1], z = data[2].
Return value unpacking: Functions that return tuples or lists can be unpacked directly.
def get_values():
return (2, 4, 6)
a, b, c = get_values()Asterisk unpacking: Use * to collect remaining elements into a list.
first, *rest = [2, 4, 6, 8, 10]
# first = 2, rest = [4, 6, 8, 10]Mismatched count: The number of targets must match the number of values, unless * is used.
a, b = [2, 4, 6] # ValueError: too many values to unpack
a, b, c = [2, 4] # ValueError: not enough values to unpacktype() and isinstance()
type()
type(obj) returns the exact type of an object. It is useful for introspection and for exercises that require returning types.
type(2) # <class 'int'>
type(4.2) # <class 'float'>
type("hi") # <class 'str'>
type([2, 4]) # <class 'list'>Returning types from unpacked data:
data = ["Apple", 2, 4.2]
a, b, c = data
result = (type(a), type(b), type(c)) # (str, int, float)isinstance()
isinstance(obj, type) returns True if the object is an instance of the given type or of a subclass of that type. It is the preferred way to check types before conversion or branching.
isinstance(2, int) # True
isinstance(4.2, float) # True
isinstance("hi", str) # True
isinstance(2, (int, float)) # True - tuple of typesSubclass handling: isinstance() returns True for subclasses; type() checks only the exact type.
class Child(list):
pass
c = Child()
type(c) == list # False - exact type is Child
isinstance(c, list) # True - Child is a subclass of listMultiple types: Pass a tuple of types to check against any of them.
isinstance(2, (int, float)) # True
isinstance("hi", (int, float)) # Falsetype() vs isinstance()
| Aspect | type(x) == T | isinstance(x, T) |
|---|---|---|
| Exact match | Yes | Yes |
| Subclasses | No | Yes |
| Use when | Need exact type | Type check before convert |
Use isinstance() for type checks in most code; it respects inheritance and is more flexible. Use type() when the exact type must be distinguished from subclasses.
Global Variables and the global Keyword
Variables defined at module level are global. They are visible everywhere in the module. Reading a global variable inside a function does not require any special keyword.
Assignment creates a local: Assigning to a name inside a function creates a local variable by default, even if a global with the same name exists. The local shadows the global.
x = 2
def set_local():
x = 4 # local x; global x unchanged
print(x)
set_local() # 4
print(x) # 2The global keyword: Use global name to assign to a global variable from inside a function. Without it, assignment creates a local.
x = y = z = None
data = ["Apple", 2, 4.2]
def assign_globals():
global x, y, z
x, y, z = data[0], data[1], data[2]
assign_globals()
# x == "Apple", y == 2, z == 4.2Read vs write: Reading a global does not require global. Only assignment does.
count = 0
def read_global():
print(count) # OK - reads global
def write_global():
global count
count += 2 # OK - modifies globalScope Overview
| Scope | Where defined | Visibility |
|---|---|---|
| Local | Inside a function | That function only |
| Global | Module top level | Entire module |
| Built-in | Python built-ins | Everywhere |
LEGB rule: Python looks up names in order: Local → Enclosing → Global → Built-in.
Tricky Behaviors
Chained assignment with mutables
a = b = [] makes both names refer to the same list. Appending to a also affects b. Use a = []; b = [] when independent lists are needed.
Unpacking count mismatch
The number of variables must match the number of values. Use * to absorb extras: a, *rest = [2, 4, 6].
type() returns the type object
type(x) returns <class 'int'>, not the string "int". For a string name, use type(x).__name__ → "int".
Forgetting global for assignment
Assigning to a global name without global creates a local. The global remains unchanged. Use global when the function must modify the global.
Interview Questions
Why does x = y = [] create shared references?
Chained assignment binds all names to the same object. For mutable types, mutating through one name affects all. Use separate assignments for independent objects.
What happens if you unpack a sequence with the wrong number of elements?
ValueError: too many values to unpack or ValueError: not enough values to unpack. Use * to collect extras.
What does type() return?
The type object of the argument (e.g. <class 'int'>). It is not a string; use type(x).__name__ for the type name as a string.
What is the difference between type() and isinstance()?
type(x) returns the exact type of x; type(x) == int is True only when x is precisely an int. isinstance(x, int) returns True when x is an int or a subclass of int. Use isinstance() for type checks in most code; use type() when subclasses must be excluded.
x = 4
type(x) == int # True
isinstance(x, int) # True
# bool is a subclass of int
type(True) == int # False - exact type is bool
isinstance(True, int) # True - bool subclasses int
# Custom subclass
class MyInt(int):
pass
y = MyInt(6)
type(y) == int # False - exact type is MyInt
isinstance(y, int) # True - MyInt subclasses intWhen is the global keyword required?
When assigning to a global variable inside a function. Reading a global does not require it.