Python Variables and Data Types: A Practical Guide Beyond the Basics
Variables are placeholders. Data types define what kind of placeholder you have. That’s the short version. The longer version involves understanding how Python handles types differently from most compiled languages — and why that matters when you’re writing real code.
Variables in Python
A variable is created the moment you assign a value to a name. No declaration keyword, no type annotation required:
username = "alice_dev"login_count = 47session_active = Truelast_seen = NonePython figures out the type from the value on the right-hand side. This is called dynamic typing — the type is determined at runtime, not when you write the code.
Naming rules and conventions
Python enforces these rules:
- Variable names can contain letters, digits, and underscores
- They cannot start with a digit
- They are case-sensitive (
totalandTotalare different variables) - Python reserved keywords (
if,for,return,class, etc.) cannot be used as names
Beyond the rules, PEP 8 (Python’s style guide) recommends:
- Use
snake_casefor variables and functions:user_name,total_price - Use
UPPER_SNAKE_CASEfor constants:MAX_RETRIES,BASE_URL - Use descriptive names:
file_countbeatsfcevery time
# Good namingitems_in_cart = 3discount_rate = 0.15final_price = items_in_cart * 100 * (1 - discount_rate)
# Hard to followx = 3d = 0.15p = x * 100 * (1 - d)Python’s Core Data Types
Integers (int)
Whole numbers with no size limit in Python 3. You can work with arbitrarily large integers without overflow:
age = 29population = 8_100_000_000 # underscores improve readabilityfactorial_20 = 2432902008176640000
print(type(age)) # <class 'int'>Floating-point numbers (float)
Numbers with decimal points, stored as IEEE 754 double-precision values. This means they have finite precision — important to know when comparing floats:
price = 19.99temperature = -3.7
# Floating-point precision surpriseprint(0.1 + 0.2) # 0.30000000000000004print(0.1 + 0.2 == 0.3) # False
# Use round() or math.isclose() for comparisonsimport mathprint(math.isclose(0.1 + 0.2, 0.3)) # TrueStrings (str)
Sequences of characters, immutable, and enclosed in single or double quotes (interchangeable):
first_name = "Jordan"last_name = 'Kim'full_name = first_name + " " + last_name # concatenation
# f-strings for embedding variablesgreeting = f"Hello, {full_name}! You have {3} messages."Booleans (bool)
Only two values: True and False. Booleans are a subclass of int in Python — True equals 1 and False equals 0, which occasionally produces surprising arithmetic results.
is_logged_in = Truehas_permission = False
# Boolean arithmetic (rarely useful but good to know)print(True + True) # 2print(False * 10) # 0None
None is Python’s null value. It represents the intentional absence of a value — different from zero, empty string, or False:
result = None # hasn't been computed yet
def find_user(user_id): # Returns a user object if found, None if not if user_id in database: return database[user_id] return NoneChecking Types at Runtime
type()
Returns the exact class of an object:
items = [1, 2, 3]print(type(items)) # <class 'list'>print(type(items) is list) # Trueisinstance()
Checks whether an object is an instance of a class or a tuple of classes. Preferred over type() in most real code because it respects inheritance:
def process_number(value): if isinstance(value, (int, float)): return value * 2 raise TypeError(f"Expected a number, got {type(value).__name__}")
print(process_number(5)) # 10print(process_number(3.14)) # 6.28isinstance handles the case where value might be a subclass of int or float — type(value) is int would fail for subclasses, but isinstance correctly returns True.
Multiple Assignment and Unpacking
Python lets you assign multiple variables in a single line:
x, y, z = 10, 20, 30a = b = c = 0 # all three point to the same value
# Useful for swapping values — no temp variable neededx, y = y, xCommon Mistakes
Confusing None with False or 0. These are all falsy in a boolean context, but they’re not equal:
print(None == False) # Falseprint(None == 0) # Falseprint(bool(None)) # False — but None itself is not FalseReassigning to a different type. Python allows it, but it’s usually a sign of confused logic:
result = 42result = "forty-two" # legal, but why?Using mutable default arguments. This is a Python-specific trap worth knowing early:
# Wrong — the list is shared across all callsdef add_item(item, container=[]): container.append(item) return container
# Rightdef add_item(item, container=None): if container is None: container = [] container.append(item) return containerUnderstanding variables and data types well gives you a stable foundation. Python’s type system is permissive enough to move fast but strict enough to catch real errors — and once you understand the boundaries, you’ll rarely run into surprises.