Variables and Assignment
▶Variables are one of the most fundamental building blocks in any programming language. In Python, variables act as named references that point to values stored in memory, and they can be created, updated, and reused throughout a program with minimal ceremony.
- What Is a Variable? Variables are created the moment a value is assigned to them using the
=operator — there is no need for a separate declaration step as in some other languages. The same variable can be reassigned to a different value or even a different type at any time, because Python is dynamically typed and does not lock a variable to a specific data type. Descriptive variable names make code more readable and easier to maintain, helping both the original author and future collaborators understand the purpose of stored data at a glance. - Naming Rules and Conventions Variable names must start with a letter or underscore and can contain letters, digits, and underscores — names beginning with a digit are invalid and will cause a syntax error. Names are case-sensitive, so
score,Score, andSCOREare three distinct variables, each capable of holding a completely independent value. Python keywords such asif,for, andreturnare reserved and cannot be used as variable names, as doing so would conflict with the language's own syntax and raise an error. - Multiple Assignment and Unpacking Chained assignment sets multiple variables to the same value in a single line, for example
x = y = z = 0initialises all three to zero simultaneously. Tuple unpacking assigns each element of a sequence to a corresponding variable, as ina, b, c = 1, 2, 3, which is both concise and expressive. Multiple assignment improves code conciseness but should be used carefully to maintain clarity, since assigning too many variables on one line can make the code harder to read and debug.
# Simple assignment
name = "Alice"
score = 42
# Reassignment to a different type
score = "forty-two"
# Chained assignment
x = y = z = 0
# Tuple unpacking
first, second, third = 10, 20, 30
print(first, second, third) # 10 20 30
Core Data Types
▶Python provides a rich set of built-in data types that cover the most common needs in everyday programming. Understanding the characteristics of each type — and when to use it — is essential for writing correct, efficient, and readable code.
- Integers and Floating-Point Numbers Integers represent exact whole numbers with no size limit in Python, so there is no overflow for extremely large values the way there is in languages with fixed-width integers. Floats can represent decimal values but may produce small rounding errors due to binary representation, which is why financial applications often use the
decimalmodule instead. Arithmetic between anintand afloatproduces afloatresult, as Python automatically widens the result to preserve precision. - Strings Strings are immutable, meaning their contents cannot be changed after creation — any operation that appears to modify a string actually produces a brand-new string object. Individual characters in a string can be accessed using index notation, e.g.,
text[0], and negative indices count from the end, sotext[-1]retrieves the last character. String concatenation combines strings using the+operator, though for joining many strings together thejoin()method is far more efficient. f-strings allow variables and expressions to be embedded directly into string literals using curly-brace syntax, making formatted output concise and readable. - Booleans Boolean values are produced by comparison and logical operations, and they form the backbone of all conditional branching and loop control in Python.
TrueandFalseare Python keywords and must be capitalized — writingtrueorfalsein lowercase will raise aNameError. Any Python object can be evaluated as a boolean in a conditional context, with empty containers, zero, andNonebeing treated as falsy and most other values as truthy. - The None Type
Noneis the only value ofNoneTypeand is not the same as zero,False, or an empty string — it explicitly represents the absence of a value. Functions that lack a return statement implicitly returnNone, so calling such a function and using its return value without checking can lead to subtle bugs.Noneis commonly used to initialize variables that will be assigned a real value later, signalling clearly that the variable is intentionally empty at that point in the program. - Checking Data Types with
type()type()accepts any Python object and returns its class, for exampletype(3.14)returns<class 'float'>. Knowing the type of a variable is essential before performing operations that require a specific type, since Python will raise aTypeErrorif incompatible types are used together without conversion.isinstance()is preferred overtype()for type-checking in conditional statements, because it correctly handles inheritance and is considered more Pythonic.
# Integers and floats
whole = 100
decimal = 3.14
print(whole + decimal) # 103.14 (float result)
# Strings
greeting = "Hello"
print(greeting[0]) # H
name = "World"
print(f"{greeting}, {name}!")
# Booleans
print(type(True)) # <class 'bool'>
print(bool("")) # False
print(bool(42)) # True
# None
result = None
print(type(result)) # <class 'NoneType'>
# Type checking
print(isinstance(3.14, float)) # True
Operators in Python
▶Operators are the symbols that tell Python how to process and combine values. From basic arithmetic to logical decision-making, a solid understanding of Python's operator categories and precedence rules is essential for writing expressions that behave exactly as intended.
- Arithmetic Operators The
/operator always returns a float, while//performs integer (floor) division, discarding any remainder and returning the largest whole number not exceeding the result. The%operator returns the remainder of a division, making it especially useful for checking whether a number is even, odd, or divisible by some value. The**operator raises a number to a power, so2**8evaluates to256and can be combined with fractional exponents to compute roots. - Comparison Operators Comparison operators always return either
TrueorFalse, making them the natural tool for building conditions inifstatements andwhileloops. The==operator checks value equality, whileischecks object identity — two objects can be equal in value yet reside at different memory addresses. Comparisons can be chained in Python, so an expression like1 < x < 10is valid, readable, and equivalent to1 < x and x < 10. - Logical Operators
andreturnsTrueonly if both operands are true, so a single falsy operand is enough to make the entire expression falsy.orreturnsTrueif at least one operand is true, and stops evaluating as soon as a truthy value is found.notinverts a boolean expression, turningTruetoFalseand vice versa, and is often used to make conditional checks read more naturally. Python uses short-circuit evaluation, stopping as soon as the outcome is determined, which can also be used deliberately to avoid errors in compound conditions. - Assignment Operators The
=operator assigns the value on the right to the variable on the left and is not to be confused with the==equality check. Augmented operators like+=combine an arithmetic operation with assignment in one step, socount += 1is a concise equivalent ofcount = count + 1. Using augmented assignment operators improves code readability in iterative operations, such as accumulating totals or building strings in a loop. - Operator Precedence Expressions inside parentheses are always evaluated first, regardless of any other operators present, making parentheses the safest tool for enforcing a desired evaluation order. Exponentiation has higher precedence than multiplication or division, so
2 * 3**2evaluates as2 * 9 = 18, not6**2 = 36. When operators share the same precedence level, they are evaluated left to right (left associativity), with the notable exception of the exponentiation operator, which is right-associative.
# Arithmetic
print(7 / 2) # 3.5
print(7 // 2) # 3
print(7 % 2) # 1
print(2 ** 8) # 256
# Comparison
x = 5
print(1 < x < 10) # True
print(x == 5) # True
# Logical with short-circuit
print(True or 1/0) # True (right side never evaluated)
# Augmented assignment
count = 0
count += 1
print(count) # 1
# Precedence
print(2 * 3 ** 2) # 18
print((2 * 3) ** 2) # 36
Type Conversion
▶Data in real programs rarely arrives in exactly the type needed for a given operation. Python handles many type mismatches automatically, but programmers must also know how and when to convert types explicitly — and how to deal gracefully with conversions that can go wrong.
- Implicit Type Conversion Python automatically promotes
inttofloatwhen they are used together in arithmetic, ensuring that no precision is lost in the resulting value. Implicit conversion only occurs when it is safe and does not result in data loss, so Python will never silently truncate or corrupt a value behind the scenes. Incompatible type combinations, such as adding a string to a number, raise aTypeError, because Python cannot make a safe assumption about the programmer's intent in such cases. - Explicit Type Conversion with Built-in Functions
int()converts a compatible string or float to an integer, truncating any decimal portion — soint(3.9)yields3, not4.float()converts an integer or numeric string to a floating-point number, enabling decimal arithmetic even when the original value was whole.str()converts any value to its string representation, which is essential when concatenating numbers with text or writing output to a file.bool()converts a value toTrueorFalsebased on its truthiness, following the same rules that Python applies when evaluating any object in a conditional context. - Common Conversion Errors and How to Avoid Them Converting a non-numeric string to
intorfloatraises aValueError, because Python cannot interpret arbitrary text as a number. Mixing incompatible types without conversion raises aTypeError, which is Python's way of signalling that the operation is not defined for the given combination of types. Wrapping conversions intry/exceptblocks allows programs to handle invalid input gracefully, displaying a helpful error message rather than crashing unexpectedly.
# Implicit conversion
result = 4 + 1.5
print(result) # 5.5 (float)
print(type(result)) # <class 'float'>
# Explicit conversion
print(int(3.9)) # 3
print(float(7)) # 7.0
print(str(100)) # '100'
print(bool(0)) # False
print(bool("hello")) # True
# Handling conversion errors
user_input = "abc"
try:
number = int(user_input)
except ValueError:
print(f"Cannot convert '{user_input}' to an integer.")
# TypeError example
try:
result = "age: " + 30
except TypeError as e:
print(e) # can only concatenate str (not "int") to str