Python Variables

Create variables with simple assignment, understand dynamic typing, and learn multiple assignment and augmented operators.

Beginner 8 min read 8 examples

Creating Variables

A variable is created the moment you assign a value to it. No declaration keyword needed.

Python
# Assignment creates the variable
name    = "Alice"
age     = 30
height  = 1.75
is_admin = False
nothing  = None

# Print them
print(name)     # Alice
print(age)      # 30
print(height)   # 1.75
print(is_admin) # False
print(nothing)  # None

# Reassign to a new value (or even a different type)
age = 31        # update
age = "thirty"  # change type entirely (valid in Python, unusual in practice)

# Using a variable before assigning it raises NameError
# print(undefined_var)  # NameError: name 'undefined_var' is not defined

Dynamic Typing

Python determines a variable's type at runtime based on the value assigned. The same variable can hold different types at different times.

Python
x = 42
print(type(x))    # <class 'int'>

x = 3.14
print(type(x))    # <class 'float'>

x = "hello"
print(type(x))    # <class 'str'>

x = [1, 2, 3]
print(type(x))    # <class 'list'>

# isinstance() - check type (handles inheritance too)
n = 42
print(isinstance(n, int))    # True
print(isinstance(n, float))  # False
print(isinstance(n, (int, float)))  # True - check against multiple types

# Python variables are labels/references, not boxes
a = [1, 2, 3]
b = a          # b points to the SAME list
b.append(4)
print(a)       # [1, 2, 3, 4] - a is also affected!

# To get an independent copy:
c = a.copy()   # shallow copy
c.append(5)
print(a)       # [1, 2, 3, 4] - a unchanged

Naming Rules

Python
# VALID names
user_name   = "Alice"    # snake_case - preferred
userName    = "Alice"    # camelCase - valid but not Pythonic
_private    = "hidden"   # underscore prefix = private by convention
__dunder__  = "special"  # double underscores = dunder (magic)
x           = 10         # single letter (ok for math/loops)
i           = 0          # loop counter
my_var_2024 = True       # letters, digits, underscores - any order

# INVALID names
# 2fast = True    # SyntaxError: cannot start with a digit
# my-var = True   # SyntaxError: hyphens not allowed
# my var = True   # SyntaxError: spaces not allowed
# class = True    # SyntaxError: 'class' is a reserved keyword

# Python reserved keywords - cannot use as variable names
import keyword
print(keyword.kwlist)
# ['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await',
#  'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except',
#  'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is',
#  'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try',
#  'while', 'with', 'yield']

Multiple Assignment

Python
# Assign multiple variables on one line
x, y, z = 1, 2, 3
print(x, y, z)  # 1 2 3

# Swap values without a temp variable
a, b = 10, 20
a, b = b, a     # swap
print(a, b)     # 20 10

# Unpack from a list or tuple
first, second, third = [10, 20, 30]
print(first)    # 10

# Star unpacking - collect the rest
head, *tail = [1, 2, 3, 4, 5]
print(head)  # 1
print(tail)  # [2, 3, 4, 5]

first, *middle, last = [1, 2, 3, 4, 5]
print(first)   # 1
print(middle)  # [2, 3, 4]
print(last)    # 5

# Assign the same value to multiple variables
a = b = c = 0
print(a, b, c)  # 0 0 0

# Walrus operator := (Python 3.8+) - assign inside an expression
data = [1, 2, 3, 4, 5]
if (n := len(data)) > 3:
    print(f"List has {n} items")  # List has 5 items

Augmented Assignment

Augmented assignment operators combine an operation with assignment. They are shorthand for x = x op value.

Python
x = 10

x += 5   # x = x + 5  -> 15
x -= 3   # x = x - 3  -> 12
x *= 2   # x = x * 2  -> 24
x /= 4   # x = x / 4  -> 6.0  (always float)
x //= 2  # x = x // 2 -> 3.0  (floor division)
x **= 3  # x = x ** 3 -> 27.0 (power)
x %= 5   # x = x % 5  -> 2.0  (modulo)

# Works on strings too
greeting = "Hello"
greeting += ", World!"
print(greeting)  # Hello, World!

# Works on lists
items = [1, 2]
items += [3, 4]  # extends the list
print(items)     # [1, 2, 3, 4]

# Note: Python has no ++ or -- operators
# Use x += 1 instead of x++

Constants

Python has no built-in constant mechanism. By convention, variables named in ALL_CAPS are treated as constants - not meant to be changed.

Python
# Convention: UPPER_SNAKE_CASE signals "do not change this"
MAX_CONNECTIONS = 100
DEFAULT_TIMEOUT = 30
PI = 3.14159265358979
BASE_URL = "https://api.example.com"
DEBUG = False

# Python does not prevent reassignment - it is a convention only
MAX_CONNECTIONS = 200  # technically allowed, but violates convention

# For true immutability, use a frozen data class or named tuple
from typing import Final

# Final (Python 3.8+) - type checkers enforce it, runtime does not
MAX_SIZE: Final = 1000
# MAX_SIZE = 2000  # mypy/pylance warns: Cannot assign to final variable

# Module-level constants go in a separate constants.py or config.py
# and are imported where needed:
# from config import MAX_CONNECTIONS, BASE_URL

Deleting Variables

Python
x = 42
print(x)  # 42

del x     # delete the variable (removes the name binding)
# print(x)  # NameError: name 'x' is not defined

# del can remove list items, dict keys
fruits = ["apple", "banana", "cherry"]
del fruits[1]          # removes "banana"
print(fruits)          # ['apple', 'cherry']

data = {"a": 1, "b": 2}
del data["a"]
print(data)            # {'b': 2}

# del does not necessarily free memory immediately
# Python's garbage collector handles that when there are no more references

Scope Introduction

Variables have a scope - where in the code they are accessible. A full scope deep-dive is in the Functions lesson, but here are the basics.

Python
# Module level (global) - accessible anywhere in the file
global_var = "I am global"

def my_function():
    local_var = "I am local"   # only accessible inside this function
    print(global_var)          # can read globals
    print(local_var)           # can read locals

my_function()
print(global_var)   # works
# print(local_var)  # NameError - local_var doesn't exist here

# global keyword - modify a global variable inside a function
count = 0

def increment():
    global count   # declare intention to modify the global
    count += 1

increment()
print(count)  # 1

# Best practice: avoid global variables; pass values as arguments instead

Frequently Asked Questions

No. Unlike Java or C, Python variables do not need to be declared before use. Simply assign a value and the variable is created: x = 10. Python infers the type from the value. There is no int x; or var x;. If you try to use a variable before assigning it, Python raises a NameError.

Python variables are references (labels) pointing to objects in memory. When you write x = 5, Python creates the integer object 5 and makes x point to it. When you write y = x, both x and y point to the same object. For immutable objects (int, str, tuple) this distinction usually does not matter. For mutable objects (list, dict) it matters a lot: y = my_list; y.append(1) modifies the same list that my_list references.

Use type(variable) which returns the type object: type(42) returns <class 'int'>. For a simple check, compare with isinstance(x, int) which returns True/False and also handles inheritance. Prefer isinstance() over type() == in production code because it respects class hierarchies.

The walrus operator (:=), added in Python 3.8, assigns a value to a variable as part of an expression. It is useful to avoid computing a value twice: if (n := len(data)) > 10: print(n) - computes len(data) once and uses the result in both the condition and the body. Use it sparingly - only when it genuinely improves readability.