Python Syntax, Variables and Data Types for Beginners
ProgrammingLesson 1 of 45 min read
What you'll learn
- Write valid Python using indentation, comments and the print function
- Explain what a variable is in Python and why two names can point at one object
- Choose between int, float, Decimal, str, bool and None for a given piece of data
- Convert between types safely and read the error when a conversion fails
On this page
Open a Python prompt and type 0.1 + 0.2. The answer is 0.30000000000000004, and a lot of beginners conclude that Python cannot do arithmetic. It can. What you are seeing is a consequence of how computers store decimal fractions, and it is the quickest way into the real subject of this lesson: every value in Python has a type, and the type decides what operations mean and which surprises are waiting for you.
We will follow one object through the whole lesson: a parcel that arrives at a self-service locker kiosk. It has a locker number, a weight, a recipient, a fragile flag and, at first, no pickup code.
Syntax: indentation is the structure
Python has no braces and no semicolons. A new line is a new statement, and the amount of leading whitespace shows which block a line belongs to. The convention is four spaces per level. A # starts a comment that runs to the end of the line. A name may contain letters, digits and underscores but cannot start with a digit, and by convention variables use lower_snake_case.
# locker.py - one parcel arrives at a locker kiosk
locker_id = 14 # int
parcel_weight_kg = 2.35 # float
recipient = "Mira Okafor" # str
is_fragile = True # bool
pickup_code = None # None: "no value yet"
print(type(locker_id), type(parcel_weight_kg), type(recipient))
print(type(is_fragile), type(pickup_code))
pickup_code = "7QX2"
print(f"Locker {locker_id}: {recipient}, {parcel_weight_kg} kg, code {pickup_code}")
print(f"Weight to the nearest tenth: {parcel_weight_kg:.1f} kg")Output
<class 'int'> <class 'float'> <class 'str'> <class 'bool'> <class 'NoneType'> Locker 14: Mira Okafor, 2.35 kg, code 7QX2 Weight to the nearest tenth: 2.4 kg
Notice there are no type declarations. Python is dynamically typed: the type belongs to the value, not to the name, so pickup_code could hold None one moment and a string the next. The f-string (a string starting with f) evaluates anything in braces, and a format spec such as :.1f controls how it is shown. Use f-strings by default; they are shorter and less error-prone than concatenation with +.
The types you will use every day
| Type | Example | Mutable? | Use it for |
|---|---|---|---|
| int | 14, -3, 1_000_000 | No | Counts, IDs, whole quantities (no size limit) |
| float | 2.35, 1e-3 | No | Measurements where tiny rounding error is acceptable |
| Decimal | Decimal("1.10") | No | Money and anything needing exact decimal digits |
| str | "7QX2" | No | Text of any length |
| bool | True, False | No | Yes/no facts and conditions |
| NoneType | None | No | The deliberate absence of a value |
A float is a binary approximation, so values like 0.1 cannot be stored exactly. For weights and temperatures this does not matter. For money it does, and the fix is either integer cents or decimal.Decimal built from a string. Building a Decimal from a float just copies the float's error into it.
from decimal import Decimal
print(0.1 + 0.2)
print(0.1 + 0.2 == 0.3)
fee_float = 1.10 * 3
fee_decimal = Decimal("1.10") * 3
fee_cents = 110 * 3
print(fee_float)
print(fee_decimal)
print(fee_cents / 100)
days_stored = 17
print(days_stored / 7) # true division -> float
print(days_stored // 7) # floor division -> whole weeks
print(days_stored % 7) # remainder -> leftover days
print(divmod(days_stored, 7))Output
0.30000000000000004 False 3.3000000000000003 3.30 3.3 2.4285714285714284 2 3 (2, 3)
Variables are labels, not boxes
In Python, shelf_b = shelf_a does not copy anything. It sticks a second label on the same object. For immutable values like numbers and strings this never matters, because you cannot change the object in place. For mutable ones such as lists it matters a great deal.
shelf_a = ["envelope", "box"]
shelf_b = shelf_a # a second label on the SAME list
shelf_b.append("tube")
print(shelf_a)
print(shelf_a is shelf_b)
shelf_c = list(shelf_a) # a real copy
shelf_c.append("crate")
print(shelf_a, shelf_c)
code = "7qx2"
try:
code[0] = "9"
except TypeError as err:
print("TypeError:", err)
code = code.upper() # builds a NEW string and re-labels it
print(code)
raw = "12"
print(raw * 2)
print(int(raw) * 2)
try:
int("12 kg")
except ValueError as err:
print("ValueError:", err)Output
['envelope', 'box', 'tube'] True ['envelope', 'box', 'tube'] ['envelope', 'box', 'tube', 'crate'] TypeError: 'str' object does not support item assignment 7QX2 1212 24 ValueError: invalid literal for int() with base 10: '12 kg'
The last lines show why conversions matter. Anything typed by a user or read from a file arrives as a string, and "12" * 2 repeats the text rather than doing arithmetic. int("12 kg") fails loudly with a ValueError, which is what you want: you will learn how to catch it in files, errors and modules.
Truthiness and None
Conditions in Python accept any value. Zero, empty strings, empty collections and None count as false; nearly everything else counts as true. That lets you write label = status or "unknown". It also hides a trap: if weight: is false for a weight of 0.0, which might be a valid reading, so when None is the thing you mean to test, write if weight is None. Use is only for None (and True/False); use == to compare values.
Common mistakes and the errors they produce
- Mixing indentation. A tab in one line and spaces in the next raises
IndentationErrororTabError. Configure your editor to insert four spaces. - Concatenating text and numbers.
"Locker " + 14raisesTypeError: can only concatenate str (not "int") to str. Use an f-string. - Using floats for prices. The total drifts by fractions of a cent and a comparison like
total == 3.3silently fails. UseDecimalor integer cents. - Expecting `=` to copy a list. Both names change together, which shows up as data mysteriously altered somewhere else. Copy with
list(x),x.copy()orx[:]. - Using `is` to compare numbers or strings. Modern Python even warns with
SyntaxWarningwhen you writex is 10. Use==.
How this shows up in real projects and interviews
In real code, the types in this lesson decide whether a data pipeline is trustworthy. Billing, tax and inventory code almost always avoids binary floats for exactly the reason above, and a surprising share of production bugs are a string that should have been an int or a None that nobody checked. Interviewers use short questions to test the same ideas: what does a = b = [] do, why is 0.1 + 0.2 != 0.3, what is the difference between == and is. If you can answer by describing labels and objects, you are ahead of most candidates. When you are ready to store many values, continue to lists, dicts and sets.
Try it yourself
Write parcel.py that stores a parcel's width, height and depth in centimetres (read them as strings first, like "30"), converts them to integers, computes the volume, and prints a line such as Volume: 18000 cm3 (fits small locker: True). A small locker holds up to 20000 cm3. Then make the program print a friendly message instead of crashing if one of the values is "30cm".
Show a hint
Wrap the int() conversions in try / except ValueError. You will meet the full pattern in the last lesson, but the idea is the same as the int("12 kg") example above.
Key takeaways
- Indentation defines blocks in Python; use four spaces and f-strings for output.
- Types belong to values. Check with
type()and convert explicitly withint(),str()and friends. - Floats are approximations; use
Decimal(from strings) or integer cents for money. - Assignment attaches a label to an object; mutable objects like lists change for every label that points at them.
- Test for missing values with
is None, not with truthiness.
Test yourself
A trick from this lesson's ride: Binary can't write 0.1 exactly, just as decimal can't write 1/3 exactly Four more tricks like it wait along the route, each followed by a question.
Frequently asked questions
Why does 0.1 + 0.2 not equal 0.3 in Python?
Floats are stored in binary, and 0.1 and 0.2 have no exact binary representation, so the sum is a hair above 0.3. Every language using IEEE 754 doubles behaves the same way. Use math.isclose to compare floats, or Decimal when you need exact decimal digits such as money.
What is the difference between == and is in Python?
== asks whether two objects have equal values. is asks whether they are the very same object in memory. Use == for numbers, strings and lists, and use is only to compare with None, as in if value is None.
Do I need to declare variable types in Python?
No. Python is dynamically typed, so the type is attached to the value and you can rebind a name to a different type. You can add optional type hints such as weight: float = 2.35, but Python does not enforce them at runtime; tools like mypy and your editor use them.