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:
| Category | Keywords |
|---|---|
| Special values | True, False, None |
| Logical operators | and, or, not, in, is |
| Branching | if, elif, else |
| Loops | for, while, break, continue, pass |
| Functions & classes | def, return, lambda, class, yield |
| Error handling | try, except, finally, raise, assert |
| Module imports | import, from, as |
| Variable scope | global, nonlocal, del |
| Async | async, await |
| Context manager | with |
# 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:
| Type | Convention | Example |
|---|---|---|
| Variable | snake_case | file_name, total_price |
| Function | snake_case | compute_score(), read_data() |
| Class | PascalCase | UserData, HttpClient |
| Constant | UPPER_SNAKE_CASE | MAX_RETRY, API_KEY |
| Module/file | snake_case | utils.py, data_parser.py |
| Package/folder | snake_case | my_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:
- Source Code (.py): The text file containing the Python code you wrote.
- 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.
- Bytecode Compiler: Converts the AST into low-level instructions called bytecode.
- Bytecode (.pyc): The compiled result in bytecode instructions (usually stored in a
__pycache__folder as.pycfiles so it doesn’t need to be recompiled on the next run). - 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 orstr.format().- input() always returns a string — convert types with
int(),float(), etc. before using them in numeric operations.- Follow PEP 8 conventions —
snake_casefor variables and functions,PascalCasefor classes,UPPER_SNAKE_CASEfor constants.- Import explicitly, not wildcards —
from math import pi, sqrtis far better thanfrom math import *.