Core Syntax #

Python was designed around the philosophy that code should read like plain text. That philosophy shows up directly in its syntax: no curly braces {} to mark blocks, no semicolons ; at the end of lines, and code structure defined by consistent indentation. If you’re coming from a language like Java or C, this feels strange at first — but it’s exactly what makes Python code read almost like pseudocode. This article covers the Python syntax foundations you need to understand before writing any code.

Indentation as Block Structure #

This is the most fundamental thing that sets Python apart from most other languages. In Python, indentation isn’t just style — indentation is syntax. The Python interpreter uses indentation to determine where a block of code starts and ends.

# ANTI-PATTERN: no indentation inside an if block
if True:
print("this will error")  # IndentationError

# CORRECT: code blocks must be indented one level
if True:
    print("this is fine")

The indentation rules you need to remember:

# Use 4 spaces per indentation level (PEP 8 standard)
def compute_grade(score):
    if score >= 90:
        return "A"
    elif score >= 75:
        return "B"
    elif score >= 60:
        return "C"
    else:
        return "D"

# Nested blocks add another 4 spaces per level
for i in range(3):          # level 1: 0 spaces
    for j in range(3):      # level 2: 4 spaces
        if i == j:          # level 3: 8 spaces
            print(i, j)     # level 4: 12 spaces
Don’t mix tabs and spaces in a single file. Python 3 rejects files that mix both and throws a TabError. Configure your editor to convert Tab to 4 spaces automatically — almost every modern editor supports this.

Statement Structure #

Each line in Python is one statement by default. Python doesn’t need a terminator at the end of a line like the ; that’s mandatory in C, Java, or PHP.

# ANTI-PATTERN: semicolon at the end of a line (not an error, but unidiomatic)
name = "Alice";
age = 25;
print(name);

# CORRECT: no semicolons
name = "Alice"
age = 25
print(name)

Multiple statements are allowed on one line using semicolons, but this is generally avoided because it hurts readability:

# ANTI-PATTERN: several statements on one line
x = 1; y = 2; z = 3

# CORRECT: one statement per line
x = 1
y = 2
z = 3

Continuing Long Lines #

If a statement is too long, you can continue it on the next line in two ways:

# Way 1: backslash as a line continuation (less preferred)
total = exam_score + assignment_score + \
        lab_score + attendance_score

# Way 2: wrap it in parentheses (preferred)
total = (
    exam_score
    + assignment_score
    + lab_score
    + attendance_score
)

# This also works for lists, dicts, and function calls
favorite_colors = [
    "red",
    "blue",
    "green",
    "yellow",
]

Keywords #

Keywords are words that already have special meaning in Python and can’t be used as variable names, function names, or any other identifier.

import keyword
print(keyword.kwlist)

Output:

['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await',
 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except',
 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is',
 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try',
 'while', 'with', 'yield']

Here’s the list of keywords and what they do:

CategoryKeywords
Special valuesTrue, False, None
Logical operatorsand, or, not, in, is
Branchingif, elif, else
Loopsfor, while, break, continue, pass
Functions & classesdef, return, lambda, class, yield
Error handlingtry, except, finally, raise, assert
Module importsimport, from, as
Variable scopeglobal, nonlocal, del
Asyncasync, await
Context managerwith
# ANTI-PATTERN: using a built-in name as a variable
list = [1, 2, 3]    # shadows the built-in 'list'
type = "integer"    # shadows the built-in 'type'
id = 42             # shadows the built-in 'id'

# CORRECT: use descriptive names that don't collide
number_list = [1, 2, 3]
data_type = "integer"
user_id = 42

Expressions and Values #

An expression is a combination of values, variables, and operators that produces a value. Every expression in Python evaluates to something you can use immediately.

# Arithmetic expressions
10 + 5          # → 15
10 / 3          # → 3.3333... (always a float in Python 3)
10 // 3         # → 3 (floor division)
10 % 3          # → 1 (remainder / modulo)
2 ** 8          # → 256 (exponentiation)

# Comparison expressions (always evaluate to True or False)
10 > 5          # → True
10 == 10        # → True
10 != 5         # → True
"abc" < "abd"   # → True (lexicographic comparison)

# Logical expressions
True and False  # → False
True or False   # → True
not True        # → False

# String expressions
"Hello" + " " + "World"   # → "Hello World" (concatenation)
"Ha" * 3                  # → "HaHaHa" (repetition)

Conditional Expressions (Ternary) #

Python has a one-line conditional expression, often called the ternary expression:

# ANTI-PATTERN: a long if-else for a simple assignment
if score >= 60:
    status = "passed"
else:
    status = "failed"

# CORRECT: ternary expression — more concise for simple cases
status = "passed" if score >= 60 else "failed"

# More examples
label = "even" if number % 2 == 0 else "odd"
absolute = x if x >= 0 else -x

Input and Output #

Input and output are the two most basic operations you need to interact with a user.

Output with print() #

# Basic print()
print("Hello, World!")          # → Hello, World!
print(42)                       # → 42
print(3.14)                     # → 3.14
print(True)                     # → True

# Printing several values at once
name = "Budi"
age = 25
print(name, age)               # → Budi 25 (space-separated)
print(name, age, sep=", ")     # → Budi, 25 (custom separator)
print(name, end="")             # no newline at the end
print(" " + str(age))          # → Budi 25 (continues on the same line)

# f-strings (the most modern and recommended way)
print(f"Name: {name}, Age: {age}")    # → Name: Budi, Age: 25
print(f"Result: {10 + 5}")            # → Result: 15
print(f"Pi: {3.14159:.2f}")           # → Pi: 3.14 (2 decimal places)
print(f"{name!r}")                    # → 'Budi' (with quotes)

Input from the User #

# input() always returns a string
name = input("Enter your name: ")
print(f"Hello, {name}!")

# ANTI-PATTERN: forgetting the type conversion when reading a number
age = input("Enter your age: ")
birth_year = 2024 - age  # TypeError: unsupported operand type(s) for -: 'int' and 'str'

# CORRECT: explicit type conversion
age = int(input("Enter your age: "))
height = float(input("Enter your height (cm): "))
birth_year = 2024 - age  # now works correctly

Naming Conventions #

Python has naming conventions agreed on by the community through PEP 8. Following them makes your code easier to read for other Python developers.

# variables and functions → snake_case
full_name = "John Doe"
student_count = 30

def compute_average(score_list):
    return sum(score_list) / len(score_list)

# constants → UPPER_SNAKE_CASE
AGE_LIMIT = 18
TAX_RATE = 0.11
DATABASE_URL = "postgresql://localhost/mydb"

# classes → PascalCase
class NewUser:
    pass

class HttpRequestHandler:
    pass

# private (convention, not enforcement) → underscore prefix
class BankAccount:
    def __init__(self):
        self._balance = 0          # protected (single underscore)
        self.__pin = "1234"        # private (double underscore)

# "magic" methods → double underscore on both sides
class Square:
    def __init__(self, side):
        self.side = side

    def __str__(self):
        return f"Square with side {self.side}"

Naming conventions summary:

TypeConventionExample
Variablesnake_casefile_name, total_price
Functionsnake_casecompute_score(), read_data()
ClassPascalCaseUserData, HttpClient
ConstantUPPER_SNAKE_CASEMAX_RETRY, API_KEY
Module/filesnake_caseutils.py, data_parser.py
Package/foldersnake_casemy_project/, data_utils/

Importing Modules #

Python uses a module system to organize code. You can import standard modules, third-party packages, or your own Python files.

# Import a whole module
import math
import os
import sys

print(math.pi)          # → 3.141592653589793
print(math.sqrt(16))    # → 4.0

# Import with an alias (handy for long names)
import numpy as np
import pandas as pd

# Import specific functions/classes
from math import pi, sqrt, floor
from os.path import join, exists, dirname

print(pi)               # → 3.141592653589793
print(sqrt(25))         # → 5.0

# ANTI-PATTERN: wildcard import — unclear what gets imported
from math import *
from os.path import *

# CORRECT: import explicitly what you need
from math import pi, sqrt
from os.path import join, exists
The import order agreed on by PEP 8: (1) Python stdlib, (2) third-party libraries, (3) local modules. Separate each group with a blank line. Tools like isort can sort them automatically.

How Python Executes Code #

Although Python is often called an interpreted language (where code executes line by line), behind the scenes Python actually goes through a compilation step first. Understanding this pipeline helps you understand why syntax errors (SyntaxError) are detected immediately, before the code ever runs.

Here’s a flow diagram of compiling and executing a Python program, from source code to output on your machine:

flowchart LR
    Source["Source Code (.py)"] --> Parser["Parser (AST)"]
    Parser --> Compiler["Bytecode Compiler"]
    Compiler --> Bytecode["Bytecode (.pyc)"]
    Bytecode --> PVM["PVM (Python Virtual Machine)"]
    PVM --> Output["Output"]

A quick explanation of the flow above:

  1. Source Code (.py): The text file containing the Python code you wrote.
  2. Parser (AST): Translates the source code into an Abstract Syntax Tree (AST) to check whether the code follows Python’s syntax rules. If something is wrong, a SyntaxError is thrown at this stage.
  3. Bytecode Compiler: Converts the AST into low-level instructions called bytecode.
  4. Bytecode (.pyc): The compiled result in bytecode instructions (usually stored in a __pycache__ folder as .pyc files so it doesn’t need to be recompiled on the next run).
  5. Python Virtual Machine (PVM): The PVM is the interpreter that reads the bytecode and translates it into machine language so your operating system can execute it.

The Most Common Syntax Errors #

Recognizing error patterns early will save you a lot of debugging time. Here are the syntax errors beginners run into most often:

# 1. Forgetting the colon after if/for/while/def/class
if x > 0        # SyntaxError: expected ':'
    print(x)

# CORRECT:
if x > 0:
    print(x)

# ---

# 2. Inconsistent indentation
def greet(name):
    print("Hello")
      print(name)   # IndentationError: unexpected indent

# ---

# 3. Unbalanced parentheses
print("Hello"     # SyntaxError: '(' was never closed
total = (1 + 2    # SyntaxError: '(' was never closed

# ---

# 4. Confusing = and ==
if x = 10:    # SyntaxError: invalid syntax (this is an assignment, not a comparison)
    pass

# CORRECT:
if x == 10:   # comparison
    pass

# ---

# 5. Unterminated string
message = "Hello world   # SyntaxError: EOL while scanning string literal

# CORRECT:
message = "Hello world"

# ---

# 6. Accessing a variable before it's defined
print(result)       # NameError: name 'result' is not defined
result = 100

Summary #

  • Indentation is syntax — Python uses indentation (4 spaces) to define code blocks, not curly braces. Consistent indentation is mandatory, not optional.
  • Don’t mix tabs and spaces — Python 3 rejects files that mix both; set your editor to convert Tab to 4 spaces.
  • No semicolons needed — one statement per line, no ; at the end. Use parentheses to continue long lines.
  • Avoid variable names that shadow built-ins — don’t use list, type, id, input, etc. as variable names.
  • f-strings are the best way to format strings — more concise and readable than % formatting or str.format().
  • input() always returns a string — convert types with int(), float(), etc. before using them in numeric operations.
  • Follow PEP 8 conventionssnake_case for variables and functions, PascalCase for classes, UPPER_SNAKE_CASE for constants.
  • Import explicitly, not wildcardsfrom math import pi, sqrt is far better than from math import *.

← Previous: Installation   Next: Comments →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact