Dataslope logoDataslope

Variables

Names, assignment, and Python's dynamic typing

In Python, a variable is a name that references an object in memory. There's no let, var, or type declaration—assignment with = creates the binding. This simplicity is powerful, but it comes with subtleties you need to understand to avoid surprises.

Every snippet on this page runs in your browser—no setup required.

Code Block
Python 3.13.2

Real-world context: Variables everywhere

Variables are the foundation of every program. In a web app, you might have user_id, session_token, and request_data. In a data pipeline, rows, schema, and output_path. In a game, player_x, enemy_health, and score. Names let you give meaning to values and reuse them throughout your code.

Names are labels, not boxes

This is the most important mental model for Python. Variables are not containers that hold values—they're labels that point to objects in memory.

When you write x = [1, 2, 3], Python creates a list object and binds the name x to it. If you then write y = x, you're binding a second name to the same list object.

Code Block
Python 3.13.2

Mutating the object through one name is visible through all names that reference it:

Code Block
Python 3.13.2

Mutable default arguments gotcha

This label-not-box model is why mutable defaults in function signatures are dangerous:

def add_item(item, items=[]):
    items.append(item)
    return items

The empty list [] is created once when the function is defined, and every call that omits items will reference the same list object. We'll revisit this when we cover functions.

To create an independent copy of a list, use .copy() or the list() constructor:

Code Block
Python 3.13.2

Dynamic typing: freedom and footguns

Python names have no fixed type. You can rebind a name to a value of any type at any time.

Code Block
Python 3.13.2
Code Block
Python 3.13.2
Code Block
Python 3.13.2

This is convenient for rapid prototyping, but it means typos in variable names are not caught until runtime. In a statically typed language like Java or Go, usre_id = 123 (instead of user_id) would be a compile error. In Python, it's just a new variable.

Type annotations: the best of both worlds

Python 3.5+ supports optional type annotations:

user_id: int = 123
name: str = "Ada"

These don't affect runtime behavior, but tools like mypy can check your code for type errors before you run it. In production codebases, type annotations are increasingly the norm—they catch bugs early and make code easier to understand.

Naming rules and conventions

A valid Python identifier:

  • Starts with a letter (including Unicode letters like é, ) or underscore _.
  • Continues with letters, digits, or underscores.
  • Is case-sensitive: Score and score are different names.
  • Cannot be a reserved keyword like if, class, def, return, pass, lambda.
Code Block
Python 3.13.2

PEP 8 style conventions

PEP 8 is Python's style guide. Following it makes your code readable to other Python developers.

KindConventionExample
Variable, functionsnake_caseuser_count, fetch_data
ConstantUPPER_SNAKE_CASEMAX_RETRIES, API_KEY
ClassPascalCaseHttpClient, UserProfile
Module filesnake_case.pydata_loader.py
Private (by convention)leading __internal_cache

Why PEP 8?

Consistency makes code easier to read. When every Python project uses snake_case for functions and PascalCase for classes, you can glance at HttpClient() and know it's a class, or at fetch_data() and know it's a function—without reading the definition.

Multiple assignment patterns

Python supports several shorthand forms that make common patterns more concise.

Code Block
Python 3.13.2
Code Block
Python 3.13.2
Code Block
Python 3.13.2

Constants?

Python has no enforced const keyword. The convention is to use ALL_CAPS names and trust developers to leave them alone.

MAX_RETRIES = 3
TIMEOUT_SECONDS = 30
API_BASE_URL = "https://api.example.com"

As of Python 3.8, the typing.Final annotation lets static type checkers enforce immutability:

from typing import Final
MAX_RETRIES: Final[int] = 3

But at runtime, nothing stops reassignment. Python trusts you.

Challenges

Challenge
Python 3.13.2
Swap two variables

Without using a temporary variable, swap the values of a and b in a single line so that a becomes "banana" and b becomes "apple".

Challenge
Python 3.13.2
Valid identifier checker

Write a function is_valid_identifier(name) that returns True if name is a valid Python identifier that is not a reserved keyword, and False otherwise. Use the str.isidentifier() method and the keyword module.

Check your understanding

QuestionSelect one

What does this code print?

nums = [1, 2, 3]
also_nums = nums
also_nums.append(4)
print(nums)

[1, 2, 3]

[1, 2, 3, 4]

A NameError

[4]

QuestionSelect one

Which of the following is not a valid Python identifier?

user_count

_private

2nd_place

café

QuestionSelect one

After this code runs, what is the value of x?

x = [10, 20]
y = x
y = y + [30]

[10, 20, 30, 30]

[10, 20]

[10, 20, 30]

An error

Next: a tour of Python's built-in data types.

On this page