Skip to main content

Basic Python Syntax and Object Model

Python code combines expressions, which produce values, and statements, which assign names, choose what runs, or define functions and classes. In the example below, temperature_c < 0 is an expression whose result determines which branch of the if statement runs. The indented lines form each branch’s code block; the line introducing a block ends with :.

temperature_c = 21.5
if temperature_c < 0:
state = "frozen"
else:
state = "liquid"

Names bind objects​

Assignment binds a name; it does not declare a storage box or copy the value:

first = [1, 2]
second = first
second.append(3)
assert first == [1, 2, 3]

Use .copy(), slicing, or a deeper-copy strategy when independent mutable state is required. Whether an operation mutates depends on the object's type and API.

Built-in value families​

  • numeric: int, float, complex, bool;
  • text and binary: str, bytes, bytearray;
  • sequences: list, tuple, range;
  • mappings and sets: dict, set, frozenset;
  • absence sentinel: None.

These categories imply different protocols. For example, a string is immutable, a list is mutable, and dictionary keys must be hashable.

Operators and comparison​

/ performs true division; // performs floor division; % gives the matching remainder. Use == for value equality and is for identity, normally with singletons such as None:

if result is None:
handle_missing_result()

Conversion is a boundary​

Constructors such as int(text), float(text), and str(value) request a conversion and may raise an exception. Do not assume user or file input has the desired form:

try:
quantity = int(raw_quantity)
except ValueError as error:
raise ValueError("quantity must be an integer") from error

Namespaces and imports​

Imports bind module objects or selected names in the current namespace:

from pathlib import Path

config_path = Path("config.json")

Prefer explicit imports and avoid wildcard imports; ownership and name origin should remain visible.

Running code and checking conversions​

These notes use Python 3.10 or later. Save code as example.py and run python3 example.py (or py -3 example.py on Windows). In an interactive interpreter, expressions are displayed automatically; in a script, use print. Use four spaces per indentation level and do not mix tabs and spaces. # starts a comment outside a string. Parentheses allow an expression to span lines.

The built-in numeric types make two different rounding choices here:

assert -7 // 3 == -3
assert -7 % 3 == 2
assert -7 == (-7 // 3) * 3 + (-7 % 3)
assert int(-2.9) == -2 # truncation toward zero
assert int(" 12 ") == 12
assert bool("False") is True

input() returns text. int("2.9") raises ValueError, whereas int(None) raises TypeError: invalid content and an unsupported input type are different failures. bool(text) tests emptiness; it does not parse words such as "False". Python integers have arbitrary precision subject to memory, while binary floats cannot represent most decimal fractions exactly: 0.1 + 0.2 != 0.3. For approximate numerical comparison, use math.isclose with tolerances chosen for the problem rather than rounding away errors indiscriminately.

A name can be rebound to another type, but an object's type determines supported operations: 3 + "4" raises TypeError. Rebinding second = [] after the earlier example does not alter first. Shallow copying only separates the outer container; nested mutable objects can remain shared.

Paste the small aliasing example into Python Tutor and step through assignment, mutation, and rebinding. Watch whether two names point to one list or to two different lists; the arrows expose the difference between changing an object and changing a name’s binding.

Sources​

Explore connectionsOpen network