← Back to Core Python
Lesson 2 · Python Foundations

Variables and Naming

Assignment, dynamic typing, naming rules, and what a name really points at.

Beginner25 min

What you will be able to do

  • Say what a variable is in Python, in terms of names and objects
  • Create, reassign, and use variables in expressions
  • Explain what dynamic typing does and does not mean
  • Apply the naming rules, and know which names are illegal and why
  • Assign several variables at once, and swap two without a temporary
  • Use type(), isinstance(), and id() to inspect what a name refers to
  • Predict what happens when two names refer to the same mutable object

The idea, in plain English

In some languages a variable is a box, and assigning to it puts a value inside. Python does not work that way, and carrying the box picture forward will make lists, dictionaries, and function arguments confusing later. It is worth replacing now.

In Python a variable is a name that refers to an object. `name = "Chandu"` creates a string object and points the name at it. The name is not the thing; it is a label attached to the thing, and the same object can have several labels.

That is why Python needs no type declaration. You never write `int age = 25`, because the type belongs to the object, not to the name. The same name can refer to an integer now and a string later - this is what dynamically typed means.

It also explains the one behaviour that surprises everyone: assignment never copies. `y = x` attaches a second label to the object x already refers to. For an integer that is harmless, because integers cannot be changed. For a list it is the source of the classic "why did my other list change" bug.

Worked example: Swapping two player names without a third variable.

What each statement actually does

Read this line by line. The column that matters is the last one - how many objects exist, and how many names are pointing at them. Nothing in this table copies anything.

Names and objects, statement by statement
x = 10Makes an int object and points the name x at it. One name, one object.
x = 20The 10 is not changed - integers cannot be changed. A new object is made and x moves to it. Nothing refers to 10 any more, so Python may discard it.
y = xNo copy. A second name is pointed at the object x already refers to. Two names, one object, and id(x) == id(y) proves it.
numbers2 = numbers1Exactly the same thing, on a list. One list object, two names - and still nothing copied.
numbers2.append(4)A list can be changed in place, and there is only one list. So numbers1 now shows [1, 2, 3, 4] as well, without ever being mentioned.
numbers2 = numbers1.copy()The only line here that makes a second object. Now appending through one name leaves the other alone.

Watch out: The surprise is never the assignment - it is the mutation. Two names on an int are harmless because an int can never change. Two names on a list, a dict, or a set are two ways to change one thing.

Dynamic typing, and what it does not mean

Python works out the type from the object you assign, so you write `age = 25` rather than `int age = 25`. The same name can later refer to something else entirely - an integer, then a string, then a list - and Python will not complain.

Dynamically typed does not mean untyped. Every object has a definite type and Python enforces it; `"5" + 5` is still an error. The difference is only that the check happens when the line runs rather than before the program starts.

Tip: Reusing one name for different types is legal but rarely kind to the reader. `data` holding an int, then a str, then a list is three variables wearing one name.

Constants are a promise, not a rule

Python has no const. What it has is a convention: an ALL_CAPS name says "treat this as fixed". MAX_RETRIES = 3 at the top of a file is a signal to other developers, and to you in six months.

Nothing stops you reassigning it. `MAX_RETRIES = 5` on the next line works fine. The uppercase is documentation that the language does not enforce, which makes it worth honouring rather than testing.

Syntax and examples

Creating variables - no type declaration
name = "Rahul" age = 25 salary = 50000.50 is_active = True print(name, age, salary, is_active)
One name, different types over time
value = 100 print(type(value)) # <class 'int'> value = "Python" print(type(value)) # <class 'str'> value = [1, 2, 3] print(type(value)) # <class 'list'>
Using variables in expressions
price = 100 quantity = 3 total = price * quantity print(total) # 300 score = 10 score = score + 5 # long form score += 5 # shorthand, same thing print(score) # 20
Multiple assignment, and the swap
# Several names at once name, age, country = "Chandu", 34, "India" # The same object to several names - useful for counters pending = completed = failed = 0 # Swapping, with no temporary variable player1 = "Rahul" player2 = "Arjun" player1, player2 = player2, player1 print(player1, player2) # Arjun Rahul
Inspecting what a name refers to
age = 34 print(type(age)) # <class 'int'> print(isinstance(age, int)) # True print(isinstance(age, str)) # False x = 100 y = x print(id(x) == id(y)) # True - one object, two names
The copy that was not a copy
numbers1 = [1, 2, 3] numbers2 = numbers1 # second name, same list numbers2.append(4) print(numbers1) # [1, 2, 3, 4] <- not a typo print(numbers2) # [1, 2, 3, 4] # When you want an actual copy, ask for one: numbers3 = numbers1.copy() numbers3.append(5) print(numbers1) # [1, 2, 3, 4] - untouched this time

Watch out: id() values differ between runs and between Python builds. Use them to compare two names in the same run, never as a stable identifier for anything.

Naming rules

Break any of the first three and Python raises a SyntaxError before your program runs at all.

Letters, digits, _

A name may contain letters, digits, and underscores. Nothing else.

user_name, item2, _internal
Never starts with a digit

2name is a syntax error. Put the digit anywhere but the front.

name2  ✓     2name  ✗
No spaces or hyphens

A space ends the name; a hyphen is read as subtraction. Use underscores.

first_name  ✓     first-name  ✗
Not a keyword

The 35 reserved words are unavailable. A trailing underscore is the usual workaround.

class_ = "Physics"
Case sensitive

name, Name, and NAME are three different variables. This catches people out in long files.

name != Name
snake_case by convention

Lowercase with underscores for variables and functions; CamelCase is reserved for classes.

total_amount, not totalAmount

Functions for inspecting objects

type()

The type of the object a name refers to.

type(34)  # <class 'int'>
isinstance()

Whether an object is an instance of a type. Preferred over type() for checks, because it accepts subclasses too.

isinstance(34, int)  # True
id()

Which object a name refers to. Two names with the same id refer to one object.

id(x) == id(y)

Try it yourself

The code does not change. Swap the content string and the program does something else entirely.

Watch the type change

“v = 1; print(type(v)); v = "1"; print(type(v))”

Prove there is no copy

“a = [1]; b = a; b.append(2); print(a)”

Now make a real copy

“a = [1]; b = a.copy(); b.append(2); print(a)”

Swap three at once

“a, b, c = 1, 2, 3; a, b, c = c, a, b; print(a, b, c)”

What usually goes wrong

Starting a name with a digit

Python reads the digit and expects a number, then finds letters. The error points at the name itself, so this one is at least easy to spot.

✗ 1name = "Rahul"
✓ name1 = "Rahul"
Spaces or hyphens in a name

A space ends the name and Python sees two things where you meant one. A hyphen is worse - it parses as subtraction, so the error can appear somewhere else entirely.

✗ first name = "Rahul"
user-name = "Rahul"
✓ first_name = "Rahul"
user_name = "Rahul"
Using a keyword as a name

class, from, is, and 32 others belong to the language. Rename, or append an underscore if the word is genuinely the right one.

✗ class = "Python"
✓ course = "Python"
Names that say nothing

x = 1000 is legal and useless. The interpreter does not care, but every person who reads it afterwards has to work out what it holds - including you.

✗ x = 1000
y = 2
z = x * y
✓ product_price = 1000
quantity = 2
total_price = product_price * quantity
Assuming assignment makes a copy

The big one, and the reason this lesson spends so long on names and objects. With a mutable object, two names mean one thing that both can change.

✗ list2 = list1        # same list
✓ list2 = list1.copy() # a new list

Best practices

  • Name things after what they hold: total_price, not x. The cost of a long name is paid once; the cost of a vague one is paid on every read.
  • Use snake_case for variables and functions, CamelCase for classes, ALL_CAPS for constants.
  • Avoid abbreviations unless your project already uses them. customer_address beats cust_addr.
  • Do not reuse one name for different types in the same function - give the second thing its own name.
  • When you want a copy of a mutable object, say so explicitly with .copy() or copy.deepcopy().
  • Reach for isinstance() rather than type() == when you are checking a type, because it handles subclasses correctly.

Practice

Write these yourself before opening anything. Getting them wrong first is most of how this sticks.

1.

Create variables for your name, age, country, city, and profession, then print them all on one line.

Show hint

print() takes several arguments and separates them with spaces.

Show solution
name = "Chandu" age = 34 country = "India" city = "Hyderabad" profession = "Engineer" print(name, age, country, city, profession)
2.

A cart holds 3 items at 1500 each. Store the price and quantity in well-named variables, work out the total, and print it.

Show solution
product_price = 1500 quantity = 3 total_price = product_price * quantity print("Total:", total_price) # Total: 4500
3.

Given a basic salary, a bonus, and a deduction, calculate and print the net salary.

Show hint

net = basic + bonus - deduction

Show solution
basic_salary = 50000 bonus = 10000 deduction = 4000 net_salary = basic_salary + bonus - deduction print("Net salary:", net_salary) # Net salary: 56000
4.

Create one variable of each type - int, float, str, bool - and print the type of each.

Show solution
count = 10 price = 99.99 title = "Python" is_ready = True print(type(count)) # <class 'int'> print(type(price)) # <class 'float'> print(type(title)) # <class 'str'> print(type(is_ready)) # <class 'bool'>
5.

Set a = 100 and b = 200, then swap them without creating a third variable. Print both to prove it worked.

Show hint

One line, with a comma on each side of the equals sign.

Show solution
a = 100 b = 200 a, b = b, a print(a, b) # 200 100
Coding challenge

Student progress calculator

Store a student, their course, and how far through it they are, then report their progress as a percentage.

It should
  • Use at least four variables, all meaningfully named
  • Store the student name, course name, completed lessons, and total lessons
  • Calculate the percentage from the variables, not from a hard-coded number
  • Print a readable report over several lines
  • Round the percentage to one decimal place
Start here
student_name = "" course_name = "" completed_lessons = 0 total_lessons = 0 # work out the percentage and print the report
Show one solution
One solution
student_name = "Rahul" course_name = "Core Python" completed_lessons = 15 total_lessons = 75 progress = round(completed_lessons / total_lessons * 100, 1) print("Student:", student_name) print("Course:", course_name) print("Completed:", completed_lessons) print("Total:", total_lessons) print("Progress: " + str(progress) + "%") # Student: Rahul # Course: Core Python # Completed: 15 # Total: 75 # Progress: 20.0%

Key points

  • A variable is a name that refers to an object. It is not a box, and the difference matters from the lists lesson onward.
  • Assignment binds a name to an object. It never copies.
  • Python is dynamically typed: the type belongs to the object, so the same name can refer to different types over time.
  • Reassigning a name does not change the old object - it points the name somewhere else.
  • Names are case sensitive, cannot start with a digit, cannot contain spaces or hyphens, and cannot be keywords.
  • snake_case for variables and functions, CamelCase for classes, ALL_CAPS for constants.
  • a, b = b, a swaps two names with no temporary variable.
  • type() gives the type, isinstance() checks it, and id() says which object a name refers to.
  • Two names on one mutable object means a change through either is visible through both.
  • Constants are a convention Python does not enforce - ALL_CAPS is a promise to other developers.

Quick check before you move on

In x = 10 then x = 20, does Python change the integer 10?
No. Integers cannot be changed. Python creates a second object and moves the name x to point at it; the 10 is left with nothing referring to it.
After x = 10 and y = x, are x and y independent copies?
No. They are two names for one object. id(x) == id(y) is True. For integers this never causes trouble, because integers cannot be changed.
Why is total_order_amount = price * quantity better than z = p * q?
Both run identically. The first tells the next reader what the number is without them having to reconstruct it - and the next reader is usually you.
What actually stops you reassigning MAX_RETRIES?
Nothing. Python does not enforce constants. ALL_CAPS is a convention that says "do not", and it depends on people honouring it.

Interview questions

What actually happens when you write x = 10 in Python?

Python evaluates the right-hand side to an object, then binds the name x to that object in the current namespace. The name holds a reference, not the value itself, which is why assignment is constant-time regardless of how large the object is.

Is Python statically or dynamically typed, and is it strongly or weakly typed?

Dynamically typed and strongly typed - two independent questions people often merge. Dynamic means types are checked at runtime rather than declared. Strong means Python will not quietly coerce between unrelated types: "5" + 5 raises a TypeError rather than guessing.

Why does changing one list appear to change another?

Because it is one list. Assignment binds a second name to the same object rather than copying it, and lists are mutable, so a change through either name is a change to the single shared object. The fix is an explicit copy - .copy() for a shallow one, copy.deepcopy() when it is nested.

What does id() return, and when would you use it?

An integer identifying an object for its lifetime - in CPython, its memory address. It is useful for demonstrating that two names refer to one object, and it is what the `is` operator compares. It is not stable across runs, so it is never an identifier to store.

Does Python have constants?

Not as a language feature. The convention is an ALL_CAPS name, which tells other developers not to reassign it, but nothing enforces that. Where enforcement genuinely matters people reach for other tools - a frozen dataclass, an Enum, or a module-level value behind a property.

Why does a, b = b, a work?

The right-hand side is evaluated first, building a tuple (b, a) from the current values. Only then is that tuple unpacked into the names on the left. Because the old values are already captured in the tuple, neither assignment can clobber the other.

What is snake_case, and where does the convention come from?

Lowercase words joined by underscores - first_name, total_amount. PEP 8 specifies it for variables, functions, and modules, with CamelCase reserved for classes and ALL_CAPS for constants. The value is consistency: a name’s shape tells you what kind of thing it is before you read it.

Quiz

  1. 1.

    What is a variable in Python?

  2. 2.

    What does it mean that Python is dynamically typed?

  3. 3.

    After numbers2 = numbers1 and numbers2.append(4), what does numbers1 contain?

  4. 4.

    What is the difference between type() and isinstance()?

  5. 5.

    How do you swap two variables without a temporary?

  6. 6.

    Which of these are invalid names, and why: 2name, user-name, class, _total?

Comments

Sign in to leave a comment. Your name and photo come from Google; nothing else is shared.

Loading comments...