Python Variables
Learn how to create and use variables in Python to store and manipulate data.
Creating Variables
Python has no command for declaring a variable. A variable is created the moment you first assign a value to it.
Example
x = 5
y = "John"
print(x)
print(y)Variables do not need to be declared with any particular type, and can even change type after they have been set.
Example
x = 4 # x is of type int
x = "Sally" # x is now of type str
print(x)Casting
If you want to specify the data type of a variable, this can be done with casting.
Example
x = str(3) # x will be '3'
y = int(3) # y will be 3
z = float(3) # z will be 3.0Get the Type
You can get the data type of a variable with the type() function.
Example
x = 5
y = "John"
print(type(x))
print(type(y))Single or Double Quotes?
String variables can be declared either by using single or double quotes:
Example
x = "John"
# is the same as
x = 'John'Case-Sensitive
Variable names are case-sensitive.
Example
a = 4
A = "Sally"
# A will not overwrite aVariable Names
A variable can have a short name (like x and y) or a more descriptive name (age, carname, total_volume). Rules for Python variables:
- A variable name must start with a letter or the underscore character
- A variable name cannot start with a number
- A variable name can only contain alpha-numeric characters and underscores (A-z, 0-9, and _ )
- Variable names are case-sensitive (age, Age and AGE are three different variables)
Example - Legal variable names:
myvar = "John"
my_var = "John"
_my_var = "John"
myVar = "John"
MYVAR = "John"
myvar2 = "John"Example - Illegal variable names:
2myvar = "John"
my-var = "John"
my var = "John"Multi Words Variable Names
Variable names with more than one word can be difficult to read. There are several techniques you can use to make them more readable:
Camel Case
Each word, except the first, starts with a capital letter:
myVariableName = "John"Pascal Case
Each word starts with a capital letter:
MyVariableName = "John"Snake Case
Each word is separated by an underscore character:
my_variable_name = "John"Python Variables - Assign Multiple Values
Many Values to Multiple Variables
Python allows you to assign values to multiple variables in one line:
Example
x, y, z = "Orange", "Banana", "Cherry"
print(x)
print(y)
print(z)One Value to Multiple Variables
And you can assign the same value to multiple variables in one line:
Example
x = y = z = "Orange"
print(x)
print(y)
print(z)Unpack a Collection
If you have a collection of values in a list, tuple etc. Python allows you to extract the values into variables. This is called unpacking.
Example
fruits = ["apple", "banana", "cherry"]
x, y, z = fruits
print(x)
print(y)
print(z)Variables Are Names, Not Boxes
A Python variable is a name bound to an object, not a container holding a value. Assignment makes the name point at an object. Two names can point at the same object.
a = [1, 2, 3]
b = a # b points at the SAME list
b.append(4)
print(a) # [1, 2, 3, 4] -> a changed too!
c = a.copy() # c is an independent copy
c.append(5)
print(a) # [1, 2, 3, 4] -> unaffectedThis "aliasing" surprises beginners with lists, dicts, and sets (mutable objects). Numbers and strings are immutable, so they never show this effect.
Naming Rules and Style
| Rule | Valid | Invalid |
|---|---|---|
| Start with letter or _ | age, _tmp | 2fast |
| Letters, digits, _ only | user_id | user-id |
| Case-sensitive | age ≠ Age | — |
| Style (PEP 8) | snake_case | camelCase |
Multiple Assignment
x = y = z = 0 # same value to several names
a, b = 1, 2 # unpack in one line
a, b = b, a # swap without a temp variable
first, *rest = [1, 2, 3, 4] # first=1, rest=[2, 3, 4]Try It Yourself
Exercise 1: Swap the values of a = 5 and b = 9 without using a third variable.
Show solution
a, b = 5, 9
a, b = b, a
print(a, b) # 9 5Exercise 2: Predict the output, then explain why.
x = [1, 2]
y = x
y.append(3)
print(x)Show solution
Output is [1, 2, 3]. y = x makes both names refer to the same list, so appending through y also changes x.
Key Takeaways
- Variables are names bound to objects; no type declaration needed.
- Assigning a mutable object creates an alias, not a copy — use
.copy()when you need independence. - Use
snake_caseand descriptive names. - Unpack and swap with
a, b = b, a.
📘 Real-World Deep Dive
Python variables are *references* (names bound to objects), not labelled boxes. That single mental model explains a huge class of bugs — aliases, mutability, default-argument traps — once you internalise it.
Real-Life Scenario
A frozen config object shared across modules. If multiple modules treat it as a copy, OK; if they mutate it, you get silent cross-talk bugs.
Real-Life Example
from dataclasses import dataclass, field, replace
@dataclass(frozen=True)
class Config:
api_base: str = "https://api.example.com"
timeout_s: float = 10.0
retries: int = 3
tags: list[str] = field(default_factory=list)
c1 = Config()
c2 = replace(c1, timeout_s=20.0) # c1 untouched
print("c1.timeout_s =", c1.timeout_s) # 10.0
print("c2.timeout_s =", c2.timeout_s) # 20.0
def add_tag(cfg: Config, tag: str) -> Config:
return replace(cfg, tags=cfg.tags + [tag])
c3 = add_tag(c1, "beta")
print(c1.tags, c3.tags) # [] ['beta']Expected Output
c1.timeout_s = 10.0
c2.timeout_s = 20.0
[] ['beta']Common mistakes
a = bfor a list/dict binds both names to the same object — usea = b.copy()orcopy.deepcopywhen you want an independent copy.- Default arguments are evaluated once at function-definition time, never per call.
def f(x, seen=[]): …accumulatesseenacross calls — useNone+ sentinel. - Rebinding a variable inside a comprehension creates a new scope (PEP 227) — don't rely on side-effects leaking out.
🚀 Performance & Best Practices
- For many small objects, prefer
__slots__on classes — it cuts memory and speeds attribute access. - Use
dataclasses.dataclass(slots=True)(Python ≥ 3.10) for the same win without boilerplate. - Local variable lookups are faster than module globals — bind hot globals to a local at the top of a function.
🧪 Try It Yourself
- Add a
frozen=True@dataclassversion ofConfigand try to mutate it — read the error. - Wrap
add_tagso it returns a frozenConfigwithout ever mutating in place. - Benchmark
dictvs.__slots__attribute access withtimeit.