Python Basics: Variables, Types, and Operators
Variables
A variable is a name that refers to a value stored in memory. You create one with a simple assignment:
message = "Hello"
count = 10
pi = 3.14159
Python is dynamically typed, so you do not declare a type when creating a variable. The interpreter figures out the type from the value you assign. This means the same variable name can refer to an integer at one point in your program and a string later. While this flexibility speeds up prototyping and keeps code concise, it also places responsibility on you to understand what type each variable currently holds, especially when passing values between functions or reading code you wrote weeks earlier. The example below demonstrates both the convenience and the potential confusion of rebinding a name to a different type.
x = 5 # x is an int
x = "five" # x is now a str, which is perfectly valid
This flexibility is convenient, but it also means you need to keep track of what type each variable holds. When programs grow beyond a few dozen lines, meaningful variable names become essential for readability. Python enforces a few simple rules about what characters a name can contain, and a broader set of community conventions about how to write them.
Variable naming rules
Python variable names must follow these rules:
- Start with a letter or underscore (
_), never a number - Contain only letters, numbers, and underscores
- Are case-sensitive (
score,Score, andSCOREare three different variables)
# Valid names
user_name = "Alice"
_count = 0
totalPrice2 = 49.99
# Invalid names
# 2nd_place = "Bob" # starts with a number
# my-variable = 10 # hyphens are not allowed
# class = "Math" # 'class' is a reserved keyword
By convention, Python programmers use snake_case for variable and function names: lowercase words separated by underscores. Constants are written in ALL_CAPS. These conventions are not enforced by the interpreter, but following them makes your code immediately recognizable to other Python developers and helps you distinguish constants from regular variables at a glance.
max_retries = 3
DEFAULT_TIMEOUT = 30
Core data types
Python has four fundamental data types you will use constantly.
int — Integers
Whole numbers, positive or negative, with no size limit. Unlike languages such as C or Java where integers have a fixed bit width and can overflow, Python’s integers can grow as large as your available memory allows. The underscore separator (available since Python 3.6) lets you break up long numeric literals for readability without affecting the value:
age = 30
population = 8_000_000_000 # underscores improve readability
negative = -42
While integers handle whole numbers perfectly, most real-world measurements involve fractional values. That is where Python’s float type comes in, providing double-precision floating-point numbers that follow the IEEE 754 standard used by virtually every modern programming language.
float — floating-point numbers
Numbers with a decimal point are automatically treated as floats, and you can use scientific notation for very large or very small values:
temperature = 98.6
ratio = 0.75
tiny = 1.5e-4 # 0.00015
Floats are convenient for most everyday calculations, but they come with an important caveat about precision. Be aware that floating-point arithmetic can produce small rounding errors because binary fractions cannot represent all decimal fractions exactly, the same way 1/3 cannot be expressed exactly as a finite decimal:
print(0.1 + 0.2) # 0.30000000000000004
This is not a Python bug. It is a property of how all computers represent decimal fractions in binary. For financial calculations where exact decimal representation matters, use the decimal module from the standard library. For most other applications, the tiny rounding differences are far below any practical tolerance and can be safely ignored.
str — Strings
Sequences of characters enclosed in quotes. Python supports single quotes, double quotes, and triple quotes for multi-line strings, giving you flexibility when your text itself contains quote characters:
first_name = "Ada"
last_name = 'Lovelace'
full_bio = """Ada Lovelace is widely regarded
as the first computer programmer."""
Strings are immutable. Methods like .upper() return a new string rather than modifying the original. This immutability is a deliberate design choice that makes strings safe to use as dictionary keys and prevents accidental side effects when passing strings between functions. If you need to build a string incrementally, collect the pieces in a list and join them at the end:
name = "python"
upper_name = name.upper()
print(name) # python (unchanged)
print(upper_name) # PYTHON
bool — Booleans
True or False (capitalized exactly this way). Booleans are a subclass of integers in Python, which means True is numerically equal to 1 and False to 0 in arithmetic contexts. This dual nature is useful for counting truthy values with sum(), but it also means you should use is rather than == when checking if something is literally True or False:
is_active = True
has_permission = False
Booleans are the result of comparison expressions and drive control flow (covered in the next tutorial).
Type checking and conversion
Python lets you inspect and change types at runtime with a handful of built-in functions. Use type() to inspect a value’s type when debugging or writing conditional logic based on the kind of data you are handling:
print(type(42)) # <class 'int'>
print(type(3.14)) # <class 'float'>
print(type("hello")) # <class 'str'>
print(type(True)) # <class 'bool'>
Convert between types with int(), float(), str(), and bool(). These conversion functions are essential when reading user input (which always arrives as a string) or when preparing values for output or comparison. Each conversion function has well-defined behavior for edge cases: int("42") works, int("hello") raises a ValueError, and bool() treats empty strings, zero, and None as False while non-empty and non-zero values become True:
number_str = "100"
number_int = int(number_str) # 100
number_float = float(number_str) # 100.0
print(str(42)) # "42"
print(bool(0)) # False
print(bool(1)) # True
print(bool("")) # False (empty string is falsy)
print(bool("hi")) # True (non-empty string is truthy)
Arithmetic Operators
Python’s arithmetic operators behave mostly as you would expect from grade-school math, with two important distinctions. Division with / always returns a float, even when both operands are integers. This differs from Python 2 where integer division would silently truncate. The // operator (floor division) explicitly performs integer division, rounding down to the nearest whole number. The modulo operator % is especially useful for testing divisibility or wrapping values within a fixed range:
a = 15
b = 4
print(a + b) # 19 addition
print(a - b) # 11 subtraction
print(a * b) # 60 multiplication
print(a / b) # 3.75 division (always float)
print(a // b) # 3 floor division
print(a % b) # 3 modulo (remainder)
print(a ** b) # 50625 exponentiation (15^4)
Python also supports augmented assignment operators that combine an arithmetic operation with assignment in a single expression. These operators modify the existing variable in place for mutable types like lists, or rebind the name for immutable types like integers and strings:
score = 10
score += 5 # same as score = score + 5 → 15
score -= 3 # 12
score *= 2 # 24
score //= 5 # 4
Comparison Operators
Comparisons return a bool and form the backbone of decision-making in Python programs. Each comparison operator answers a specific question about the relationship between two values, and Python lets you chain them together in a way that reads like natural mathematics:
x = 10
y = 20
print(x == y) # False (equal to)
print(x != y) # True (not equal to)
print(x < y) # True (less than)
print(x > y) # False (greater than)
print(x <= 10) # True (less than or equal to)
print(x >= 15) # False (greater than or equal to)
You can chain comparisons, which reads naturally and evaluates more efficiently than combining separate comparisons with and. Python evaluates each link in the chain independently, short-circuiting as soon as any link is false. This syntax is unique to Python among mainstream languages and is one of those small quality-of-life features that makes everyday code feel cleaner:
age = 25
print(18 <= age <= 65) # True; age is between 18 and 65 inclusive
String Concatenation
Comparisons and arithmetic give you logic and computation. Strings give you a way to present the results. Once you have mastered comparison logic, you will often want to assemble and display results as formatted text. Python’s string concatenation operators handle the basics of joining and repeating text. Join strings with the + operator. While this works for combining a few strings, building large strings by repeated concatenation in a loop is inefficient because Python creates a new string object on each iteration. For programmatic string building, collecting pieces in a list and calling " ".join() is the idiomatic approach:
first = "Jane"
last = "Doe"
full = first + " " + last
print(full) # Jane Doe
Repeated concatenation uses *, which is a convenient shortcut for creating repeating patterns like separators, borders, or visual dividers in terminal output. This is a small operator with a specific use case, but it is worth knowing because it is far more readable than calling "-".join([""] * 41):
print("-" * 40) # ----------------------------------------
F-Strings
F-strings (introduced in Python 3.6) are the cleanest way to embed expressions inside strings. Prefix a string with f and place any valid Python expression inside curly braces. The expression is evaluated at runtime and its string representation is inserted into the surrounding text, making f-strings both more readable and faster than older approaches like str.format() or %-formatting:
name = "Alice"
age = 30
print(f"{name} is {age} years old.")
# Alice is 30 years old.
You can put any valid expression inside the curly braces, including arithmetic, function calls, and attribute access. The format specifier after the colon controls how the resulting value is displayed. For numbers, this means you can control decimal places, add thousands separators, or pad with leading zeros without separate formatting calls:
price = 49.99
tax_rate = 0.08
print(f"Total: ${price * (1 + tax_rate):.2f}")
# Total: $53.99
The :.2f format specifier rounds the result to two decimal places. You can use :.0f for whole numbers, :.3f for three places, or replace f with e for scientific notation. For strings, format specifiers control alignment, width, and padding. For example, {name:>20} right-aligns a name in a 20-character field.
items = ["apple", "banana", "cherry"]
print(f"There are {len(items)} items.")
# There are 3 items.
Next Steps
You now have a solid grasp of variables, Python’s core types, and operators. Continue to Control Flow to learn about making decisions with if statements and repeating actions with loops.
See also
- Getting started with Python — set up your environment and run your first script
- String formatting — deeper coverage of f-strings and other formatting approaches
- Error handling — how to catch and respond to type and value errors