M02 — Chương trình đầu tiên và cú pháp nền tảng

← 01 - Cài đặt môi trường | Tiếp theo → 03 - Biến và kiểu dữ liệu

Mục tiêu module

  • Viết và chạy được chương trình Python hoàn chỉnh
  • Hiểu indentation (thụt lề) — đặc trưng quan trọng nhất của Python
  • Sử dụng thành thạo print() và comment
  • Biết quy chuẩn đặt tên theo PEP 8

Thời lượng: ~4 giờ | Tuần: 3


1. Chương trình “Hello World”

Theo truyền thống, chương trình đầu tiên của mọi ngôn ngữ là in ra dòng chữ “Hello, World!”.

Tạo file tuan-03/hello.py:

print("Hello, World!")

Chạy:

python tuan-03/hello.py

Kết quả:

Hello, World!

Mổ xẻ dòng code này

print ( "Hello, World!" )
  ↑   ↑        ↑        ↑
  │   │        │        └── Dấu ngoặc đóng
  │   │        └─────────── Argument (đối số) — dữ liệu truyền vào hàm
  │   └──────────────────── Dấu ngoặc mở
  └──────────────────────── Tên hàm (function name)
Thành phầnThuật ngữGiải thích
printfunction (hàm)Một đoạn code viết sẵn, làm nhiệm vụ in ra màn hình
()call (lời gọi)Cặp ngoặc tròn báo cho Python biết “hãy thực thi hàm này”
"Hello, World!"argument (đối số)Dữ liệu bạn đưa cho hàm xử lý
"..."string literal (chuỗi ký tự)Cặp nháy kép báo đây là văn bản, không phải tên biến

Thiếu cặp ngoặc = hàm không chạy

print("Xin chao")   # ✅ In ra: Xin chao
print               # ❌ Không in gì cả (chỉ nhắc tới tên hàm, không gọi)

Ở REPL, gõ print trơ trọi sẽ hiện <built-in function print> — Python đang nói “đây là một hàm”, chứ không thực thi nó.


2. Hàm print() chi tiết

2.1. In nhiều giá trị cùng lúc

print("Ma khach hang:", "KH001")

Kết quả:

Ma khach hang: KH001

Python tự chèn một dấu cách giữa các đối số.

print("Ho ten:", "Nguyen Van A", "-", "Tuoi:", 35)

Kết quả:

Ho ten: Nguyen Van A - Tuoi: 35

2.2. Tham số sep — đổi ký tự phân cách

print("2026", "08", "08", sep="-")

Kết quả:

2026-08-08
print("A", "B", "C", sep="")      # Không phân cách
print("A", "B", "C", sep=" | ")   # Phân cách bằng dấu gạch đứng

Kết quả:

ABC
A | B | C

2.3. Tham số end — đổi ký tự kết thúc

Mặc định, print() tự xuống dòng sau khi in (vì end="\n", trong đó \n là ký tự xuống dòng).

print("Dong 1")
print("Dong 2")

Kết quả:

Dong 1
Dong 2

Đổi end để không xuống dòng:

print("Dang xu ly", end="... ")
print("Xong!")

Kết quả:

Dang xu ly... Xong!

2.4. In dòng trống

print("Phan 1")
print()              # In một dòng trống
print("Phan 2")

print() so với SQL

Trong T-SQL bạn dùng PRINT 'text' để in ra thông báo. print() của Python tương tự, nhưng linh hoạt hơn nhiều: in được nhiều giá trị, tùy chỉnh phân cách, và in được mọi kiểu dữ liệu mà không cần ép kiểu thủ công.

Tài liệu chính thức: https://docs.python.org/3/library/functions.html#print


3. Comment — Ghi chú trong code

Comment là dòng ghi chú mà Python bỏ qua hoàn toàn khi chạy. Nó dành cho con người đọc.

3.1. Comment một dòng

Dùng dấu #:

# Đây là comment, Python không chạy dòng này
print("Dòng này chạy")   # Comment cũng có thể đặt cuối dòng lệnh

3.2. Comment nhiều dòng

Python không có cú pháp comment khối như /* ... */ của SQL. Có 2 cách:

Cách 1 — Nhiều dấu # (khuyến nghị):

# Chương trình tính tiền điện
# Tác giả: Nguyễn Văn A
# Ngày tạo: 08/08/2026
# Ghi chú: đơn giá theo biểu giá bậc thang EVN

Trong VS Code: bôi đen nhiều dòng rồi nhấn Ctrl + / để comment/bỏ comment hàng loạt.

Cách 2 — Chuỗi nhiều dòng ("""..."""):

"""
Đoạn này thực chất là một chuỗi ký tự,
không phải comment thật.
Nhưng vì không gán cho biến nào nên Python bỏ qua.
"""

Khi nào dùng """..."""?

Cú pháp này được dành riêng cho docstring (chuỗi tài liệu) — mô tả chức năng của hàm, class, module. Bạn sẽ học kỹ ở 10 - Hàm (Function). Để comment thông thường, hãy dùng #.

3.3. Viết comment thế nào cho đúng?

# ❌ Comment vô dụng — chỉ đọc lại code
x = x + 1   # Cộng x thêm 1
 
# ✅ Comment hữu ích — giải thích LÝ DO
x = x + 1   # Bù cho việc chỉ số bắt đầu từ 0 khi hiển thị cho người dùng

Nguyên tắc vàng

Code trả lời câu hỏi “làm gì”. Comment trả lời câu hỏi “tại sao”.


4. Indentation — Thụt lề (phần quan trọng nhất module này)

4.1. Vấn đề: làm sao nhóm các lệnh lại với nhau?

Hầu hết ngôn ngữ dùng dấu ngoặc nhọn hoặc từ khóa để đánh dấu khối lệnh (code block):

T-SQL:

IF @Tuoi >= 18
BEGIN
    PRINT 'Nguoi lon';
    PRINT 'Duoc phep ky hop dong';
END

C# / Java / JavaScript:

if (tuoi >= 18) {
    Console.WriteLine("Nguoi lon");
    Console.WriteLine("Duoc phep ky hop dong");
}

Python — dùng THỤT LỀ:

if tuoi >= 18:
    print("Nguoi lon")
    print("Duoc phep ky hop dong")

4.2. Quy tắc

Quy tắcNội dung
1Dòng mở đầu khối lệnh kết thúc bằng dấu hai chấm :
2Các dòng thuộc khối phải thụt vào cùng một mức
3Chuẩn PEP 8: thụt vào 4 dấu cách (space), không dùng Tab
4Dòng nào thụt về mức cũ là đã ra khỏi khối

4.3. Ví dụ minh họa mức thụt lề

print("A")              # Mức 0 — luôn chạy
 
if 5 > 3:               # Mức 0 — mở khối, có dấu :
    print("B")          # Mức 1 — thuộc khối if
    print("C")          # Mức 1 — thuộc khối if
    if 10 > 8:          # Mức 1 — mở khối lồng, có dấu :
        print("D")      # Mức 2 — thuộc khối if bên trong
    print("E")          # Mức 1 — đã ra khỏi if bên trong
print("F")              # Mức 0 — đã ra khỏi mọi khối

Kết quả:

A
B
C
D
E
F

Bây giờ thử đổi điều kiện thành sai:

print("A")
if 5 > 100:             # Điều kiện SAI
    print("B")
    print("C")
print("F")

Kết quả:

A
F

Toàn bộ khối thụt lề bị bỏ qua vì điều kiện sai.

4.4. Các lỗi thụt lề điển hình

Lỗi 1 — Thiếu thụt lề sau dấu :

if 5 > 3:
print("Sai roi")
IndentationError: expected an indented block after 'if' statement on line 1

Lỗi 2 — Thụt lề không đều

if 5 > 3:
    print("Dong 1")
        print("Dong 2")
IndentationError: unexpected indent

Lỗi 3 — Thụt lề khi không cần

print("A")
    print("B")
IndentationError: unexpected indent

Lỗi 4 — Trộn Tab và Space (nguy hiểm nhất vì mắt thường không thấy)

if 5 > 3:
    print("Dong nay dung 4 space")
	print("Dong nay dung 1 Tab")
TabError: inconsistent use of tabs and spaces in indentation

Phòng chống lỗi Tab/Space

  1. Trong VS Code, bật Editor: Render Whitespace = all (đã hướng dẫn ở 01 - Cài đặt môi trường)
  2. Bật Editor: Insert Spaces = true — VS Code sẽ tự chuyển Tab thành 4 space
  3. Khi copy code từ website về, luôn kiểm tra lại thụt lề

4.5. Vì sao Python chọn cách này?

Vì triết lý “Readability counts” (tính dễ đọc là quan trọng). Trong các ngôn ngữ khác, lập trình viên vẫn phải thụt lề cho dễ đọc, nhưng máy không bắt buộc — nên code lộn xộn vẫn chạy. Python biến quy ước thành luật, buộc mọi code Python trên thế giới đều có hình thức nhất quán.

Đây vừa là ưu điểm (code sạch), vừa là điểm gây khó chịu ban đầu.


5. Câu lệnh (Statement) và dòng

5.1. Một dòng = một lệnh

print("A")
print("B")

Python không cần dấu chấm phẩy cuối dòng (khác SQL, C#, Java).

Về mặt kỹ thuật thì ; vẫn hợp lệ để viết nhiều lệnh trên một dòng:

print("A"); print("B")    # Chạy được nhưng KHÔNG NÊN

PEP 8 khuyến cáo không làm vậy. Mỗi lệnh một dòng.

5.2. Ngắt một lệnh dài thành nhiều dòng

Cách 1 — Ngắt bên trong dấu ngoặc (khuyến nghị):

print("Ma hoa don:", "HD001",
      "Ngay:", "08/08/2026",
      "So tien:", 1500000)

Python hiểu lệnh chưa kết thúc vì ngoặc tròn chưa đóng.

Cách 2 — Dấu gạch chéo ngược \:

tong = 100 + \
       200 + \
       300

Cách này dễ lỗi (nếu có khoảng trắng thừa sau \ là hỏng). Ưu tiên cách 1.

5.3. Độ dài dòng

PEP 8 khuyến nghị tối đa 79 ký tự/dòng. Thực tế nhiều dự án dùng 88 hoặc 100. Với bạn: cứ giữ dòng ngắn, dễ đọc.


6. Case-sensitivity — Phân biệt hoa thường

Python phân biệt tuyệt đối chữ hoa và chữ thường:

print("OK")     # ✅ Đúng
Print("OK")     # ❌ NameError: name 'Print' is not defined
PRINT("OK")     # ❌ NameError: name 'PRINT' is not defined

Điều này áp dụng cho mọi thứ: tên hàm, tên biến, từ khóa.

so_luong = 10
print(So_Luong)   # ❌ NameError — 'So_Luong' khác 'so_luong'

Bẫy lớn cho dân SQL

Trong T-SQL, SELECT, select, Select đều như nhau; tên cột MaKH và makh cũng thường như nhau (tùy collation). Trong Python không có chuyện đó. Một chữ hoa sai là chương trình dừng.


7. Keywords — Từ khóa dành riêng

Python có một danh sách từ khóa mà bạn không được dùng làm tên biến. Xem danh sách:

import keyword
print(keyword.kwlist)

Kết quả (Python 3.14):

['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']

Ví dụ lỗi:

class = "Ke toan"     # ❌ SyntaxError — 'class' là từ khóa
if = 5                # ❌ SyntaxError — 'if' là từ khóa

Cách xử lý: đổi tên.

lop_hoc = "Ke toan"   # ✅
dieu_kien = 5         # ✅

8. Quy chuẩn đặt tên — PEP 8

PEP 8 là tài liệu chính thức quy định phong cách viết code Python: https://peps.python.org/pep-0008/

8.1. Quy tắc đặt tên biến/hàm

Quy tắcVí dụ đúngVí dụ sai
Chữ thường, các từ nối bằng _ (snake_case)so_luong, tong_tienSoLuong, TongTien
Không bắt đầu bằng sốbien_11_bien
Không dùng dấu tiếng Việtso_luongsố_lượng (chạy được nhưng KHÔNG NÊN)
Không dùng khoảng trắngma_khach_hangma khach hang
Tên có nghĩatong_doanh_thua, x1, temp2

Python cho phép tên biến tiếng Việt có dấu — nhưng đừng dùng

số_lượng = 10      # Chạy được! Python 3 hỗ trợ Unicode trong tên biến

Về kỹ thuật là hợp lệ. Nhưng thực tế tuyệt đối tránh: gây lỗi encoding khi chuyển máy, không đồng nghiệp nước ngoài nào đọc được, nhiều công cụ không hỗ trợ. Dùng tiếng Việt không dấu là chuẩn thực tế trong ngành phần mềm Việt Nam.

8.2. So sánh với các quy ước khác

Quy ướcHình thứcPython dùng ở đâu
snake_casetong_tienBiến, hàm, module — dùng chủ yếu
PascalCaseTongTienTên class (14 - Lập trình hướng đối tượng (OOP))
UPPER_CASETONG_TIENHằng số (constant)
camelCasetongTien❌ Không dùng trong Python (đây là của Java/C#/JavaScript)

8.3. Ví dụ code đúng chuẩn PEP 8

# Hằng số — chữ hoa toàn bộ
THUE_SUAT_VAT = 0.1
DON_GIA_DIEN_BAC_1 = 1800
 
# Biến — snake_case
so_luong_ban = 25
don_gia = 150000
thanh_tien = so_luong_ban * don_gia
tien_thue = thanh_tien * THUE_SUAT_VAT
 
print("Thanh tien:", thanh_tien)
print("Tien thue VAT:", tien_thue)
print("Tong cong:", thanh_tien + tien_thue)

9. Cấu trúc một file Python chuẩn

"""
Chương trình tính tiền hóa đơn bán hàng.
 
Tác giả: Nguyễn Văn A
Ngày tạo: 08/08/2026
"""
 
# ---------- Phần 1: Import thư viện ----------
# (chưa có ở giai đoạn này, sẽ học ở M12)
 
# ---------- Phần 2: Hằng số ----------
THUE_SUAT_VAT = 0.1
 
# ---------- Phần 3: Dữ liệu đầu vào ----------
ten_hang = "Ban lam viec"
so_luong = 3
don_gia = 2500000
 
# ---------- Phần 4: Xử lý ----------
thanh_tien = so_luong * don_gia
tien_thue = thanh_tien * THUE_SUAT_VAT
tong_cong = thanh_tien + tien_thue
 
# ---------- Phần 5: Xuất kết quả ----------
print("=" * 40)
print("HOA DON BAN HANG")
print("=" * 40)
print("Ten hang :", ten_hang)
print("So luong :", so_luong)
print("Don gia  :", don_gia)
print("-" * 40)
print("Thanh tien:", thanh_tien)
print("Thue VAT  :", tien_thue)
print("TONG CONG :", tong_cong)
print("=" * 40)

Kết quả:

========================================
HOA DON BAN HANG
========================================
Ten hang : Ban lam viec
So luong : 3
Don gia  : 2500000
----------------------------------------
Thanh tien: 7500000
Thue VAT  : 750000.0
TONG CONG : 8250000.0
========================================

Vì sao tiền thuế hiện 750000.0 có dấu chấm 0?

Vì THUE_SUAT_VAT = 0.1 là số thực (float), nên phép nhân cho ra số thực. Bạn sẽ hiểu rõ ở 03 - Biến và kiểu dữ liệu và học cách định dạng đẹp ở 05 - Chuỗi ký tự (String).


10. Thực hành bắt buộc

Bài 1 — Danh thiếp

Viết file tuan-03/danh_thiep.py in ra danh thiếp của bạn:

+--------------------------------+
|  NGUYEN VAN A                  |
|  Chuyen vien phan mem ERP      |
|  Email: nva@example.com        |
|  DT: 0900.000.000              |
+--------------------------------+

Gợi ý: chỉ dùng nhiều lệnh print().

Bài 2 — Thử nghiệm với sep và end

Chỉ dùng một lệnh print() duy nhất để in ra:

2026/08/08

Bài 3 — Bảng cửu chương 2 (viết tay, chưa dùng vòng lặp)

2 x 1 = 2
2 x 2 = 4
...
2 x 10 = 20

Viết 10 lệnh print(). Sau khi làm xong, hãy cảm nhận sự “cực nhọc” này — đến 07 - Vòng lặp (for-while) bạn sẽ làm được bằng 2 dòng.

Bài 4 — Cố tình gây lỗi (BẮT BUỘC)

Tạo file tuan-03/thu_loi.py. Lần lượt viết từng đoạn dưới đây, chạy, chép lại nguyên văn thông báo lỗi vào Lỗi thường gặp và cách đọc lỗi:

# Thử 1
print("Xin chao"
 
# Thử 2
Print("Xin chao")
 
# Thử 3
print(Xin chao)
 
# Thử 4
if 5 > 3:
print("Khong thut le")
 
# Thử 5
    print("Thut le thua")
 
# Thử 6
class = 10

Với mỗi lỗi, ghi lại: tên lỗi (dòng cuối cùng) và số dòng Python báo.

Bài 5 — Hóa đơn của riêng bạn

Sửa chương trình mẫu ở mục 9 thành hóa đơn cho một mặt hàng bạn tự chọn, có thêm dòng chiết khấu 5%.


11. Tự kiểm tra

  • Tôi viết được chương trình nhiều dòng print() và chạy được
  • Tôi giải thích được vì sao Python dùng thụt lề thay cho BEGIN...END
  • Tôi phân biệt được IndentationError và TabError
  • Tôi biết dùng # để comment và hiểu comment nên viết gì
  • Tôi biết dùng sep và end của print()
  • Tôi đặt tên biến theo snake_case, không dấu tiếng Việt
  • Tôi biết danh sách từ khóa và cách tra bằng keyword.kwlist

12. Tài liệu chính thức

NguồnNội dungLink
Python Tutorial — An Informal IntroductionBài học nhập môn chính thứchttps://docs.python.org/3/tutorial/introduction.html
PEP 8 — Style Guide for Python CodeQuy chuẩn viết codehttps://peps.python.org/pep-0008/
Built-in Functions — print()Tài liệu hàm printhttps://docs.python.org/3/library/functions.html#print
Language Reference — Lexical analysisQuy tắc thụt lề, dòng logichttps://docs.python.org/3/reference/lexical_analysis.html
KeywordsDanh sách từ khóahttps://docs.python.org/3/reference/lexical_analysis.html#keywords

Tiếp theo → 03 - Biến và kiểu dữ liệu