VS Vikesh Singh

Courses Python Lesson 2

PYTHON · LESSON 2 OF 2

Python Fundamentals: Variables, Operators, and Collections

· 3 min read

What a variable actually is in Python, why mutability explains half the confusing bugs, and the real differences between list, tuple, and set.

Python infers types automatically, which is convenient until you need to reason about why two variables that look equal behave differently in an if check. This post is the second-session recap from an AI Forward Deployed Engineer bootcamp: variables, data types, operators, and the first three collection types.

Variables are names, not boxes

A variable doesn't store a value — it stores the address of an object in memory.

a = 3
print(a)        # 3
print(id(a))    # numeric representation of the address a points to

Naming rules: letters, digits, and underscores only, can't start with a digit, no spaces, and use snake_case — first_name, not firstName. Names should be meaningful: age, not a.

first_name = "Vikesh Singh"

The type categories

Number covers int, float, and the rarely-used complex. Boolean is just bool — True or False, capitalized. Text is str. Sequence covers list, tuple, and range. Set is set. Mapping is dict. And None is its own null type, NoneType.

Python infers the type — no declaration needed. Use type(x) to check one:

num_integer = 12
print(type(num_integer))   # <class 'int'>

num_float = 12.0           # any decimal point makes it a float
print(type(num_float))     # <class 'float'>

Mutable vs. immutable

This is the part that actually explains confusing bugs. Immutable types — int, float, bool, str, tuple — get a new memory address every time the value changes. Mutable types — list, dict, set — keep the same address and change in place.

a = 10
print(id(a))
a = a + 1       # new address — int is immutable
print(id(a))    # different from before

nums = [10]
print(id(nums))
nums.append(20) # same address — list is mutable
print(id(nums))

Operators, the ones that actually come up

Arithmetic: +, -, *, / (true division, keeps the decimal), // (floor division, drops it), % (modulus), ** (exponent).

Comparison always returns a boolean: ==, !=, >, <, >=, <=.

Assignment includes the compound forms — x += 5 unwraps to x = x + 5.

Logical operators only make sense on booleans: and is true only if both sides are, or is true if either side is, not flips the value.

age = 25
has_id = True
can_enter = age > 18 and has_id   # True

Identity (is / is not) checks whether two names point to the same object — not whether the values are equal.

a = 10
b = 20
c = 10
print(a is b)   # False — different objects
print(a is c)   # True — Python reuses the same small-int object

Operator precedence, high to low: parentheses, exponent, unary (not, bitwise NOT), multiplication/division/floor-division/modulus, addition/subtraction, bitwise shifts/ops, comparisons, not, and, or. When in doubt, use parentheses and skip the lookup.

Collections: list, tuple, set

list is ordered, mutable, and allows duplicates. tuple is ordered, immutable, and allows duplicates. set is unordered, mutable, and does not allow duplicates.

List is the general-purpose ordered collection:

numbers = [10, 20, 30]
numbers.append(1000)   # add at end
numbers.remove(30)     # remove first match by value
numbers.pop(0)         # remove and return value at index
numbers.insert(1, 5)   # insert value at index
numbers.sort()         # sort in place
numbers.reverse()      # reverse in place

Tuple is ordered and immutable — use it for data that should never change. A single-element tuple needs a trailing comma: (1,), since (1) without it is just the int 1.

Set is unordered, mutable, and drops duplicates automatically:

numbers = {1, 1, 2, 3, 4, 5}   # duplicates collapse
numbers.add(4)
numbers.discard(400)            # removes by value if present, no error if not

Sets have no positional indexing — there's no my_set[0]. Dictionary and string operations carry over to the next session.