Skip to content · ⁨Bỏ qua nội dung⁩
Subjects · ⁨Môn học⁩
  • 1 Getting started · ⁨Bắt đầu⁩
    1.1

    Chương trình đầu tiên của bạn

    English

    Python runs your code one line at a time. Each line is a statement 语句. A program 程序 is just a list of statements that run from top to bottom.

    The print() function shows text on the screen. This is called output 输出. Text inside quotes is a string 字符串.

    • Each print() starts a new line.
    • Quotes can be "double" or 'single' — both make a string.
    • A program does nothing until you run it.
    Tiếng Việt

    Python chạy mã của bạn từng dòng một. Mỗi dòng là một mệnh lệnh. Một chương trình chỉ là một danh sách các mệnh lệnh được thực thi từ trên xuống dưới.

    Hàm print() hiển thị văn bản lên màn hình. Đây được gọi là đầu ra. Văn bản nằm trong dấu ngoặc kép là chuỗi (string).

    print("Hello, world!")
    print("I am learning Python")
    
    • Mỗi print() bắt đầu một dòng mới.
    • Dấu ngoặc có thể là "double" hoặc 'single' — cả hai đều tạo thành một chuỗi.
    • Một chương trình không làm gì cả cho đến khi bạn chạy nó.
    Source code runs through the interpreter to produce output
    Source code runs through the interpreter to produce output
    1.2

    Nhận xét & phong cách viết mã

    English

    A comment 注释 starts with #. Python ignores everything after the # on that line. Comments explain your code to people; they do not change what the code does.

    Good style makes code easy to read:

    • Use clear names that say what a value means.
    • Put one statement on each line.
    • Do not add spaces at the start of a normal line. In Python, spacing at the start (indentation 缩进) has a special meaning, so a wrong space gives an error 错误.
    Tiếng Việt

    Một nhận bắt đầu bằng #. Python bỏ qua mọi thứ sau ký tự # trên dòng đó. Nhận giải thích mã của bạn cho người đọc; chúng không thay đổi hành vi của mã.

    # This line is a note for humans
    print("Hi")        # you can also comment at the end of a line
    

    Phong cách tốt giúp mã dễ đọc hơn:

    • Sử dụng tên rõ ràng để thể hiện ý nghĩa của giá trị.
    • Đặt một câu lệnh trên mỗi dòng.
    • Không thêm khoảng trắng ở đầu một dòng bình thường. Trong Python, khoảng trắng ở đầu (độ thụt vào) có ý nghĩa đặc biệt, vì vậy khoảng trắng sai sẽ gây ra lỗi.
    1.3

    Đầu vào, xử lý, đầu ra

    English

    Many programs follow a simple plan: input 输入 → process → output. You get some data, do something with it, then show a result.

    The input() function reads text that the user types. It always gives back a string.

    • input() waits for the user to type and press Enter.
    • Store the typed text in a variable 变量 so you can use it later.
    • Because input() returns a string, change it with int(...) first if you need a number.

    Common mistakes

    • Forgetting the quotes: print(Hello) looks for a variable named Hello and raises a NameError. Text needs quotes: print("Hello").
    • A stray space at the start of a line: Python reads indentation as structure, so it raises an IndentationError.
    • Assuming input() returns a number. It always returns a string, so wrap it in int(...) before doing any maths.
    Tiếng Việt

    Nhiều chương trình tuân theo kế hoạch đơn giản: đầu vào → xử lý → đầu ra. Bạn nhận được dữ liệu, thực hiện thao tác với nó, sau đó hiển thị kết quả.

    Hàm input() đọc văn bản mà người dùng nhập. Nó luôn trả về một chuỗi ký tự (string).

    name = input("What is your name? ")
    print("Hello, " + name)
    
    • input() chờ người dùng nhập và nhấn Enter.
    • Lưu văn bản đã nhập vào biến để sử dụng sau này.
    • Vì input() trả về chuỗi, hãy chuyển đổi nó bằng int(...) trước nếu bạn cần số.

    Lỗi thường gặp

    • Quên dấu ngoặc: print(Hello) sẽ tìm kiếm biến tên là Hello và gây ra lỗi NameError. Văn bản cần dấu ngoặc: print("Hello").
    • Một khoảng trắng thừa ở đầu dòng: Python đọc độ thụt vào như cấu trúc, nên sẽ gây ra lỗi IndentationError.
    • Giả sử rằng input() trả về số. Nó luôn trả về chuỗi, vì vậy hãy bọc nó trong int(...) trước khi thực hiện bất kỳ phép tính nào.
  • 2 Variables, types & operators · ⁨Biến, kiểu & toán tử⁩
    2.1

    Biến & gán giá trị

    English

    A variable 变量 is a name for a value 值. You make one with =, which is called assignment 赋值. The name goes on the left; the value goes on the right.

    Now age holds 17. Use the name anywhere you need the value, and change it later:

    • The = sign does not mean "equal". It means "store the right side under the left name".
    • To test if two values are equal, use == (see below).
    Tiếng Việt

    Biến là tên gọi cho một giá trị. Bạn tạo nó bằng cách gán =, còn gọi là gán giá trị. Tên biến nằm bên trái; giá trị nằm bên phải.

    age = 17
    name = "Mei"
    price = 9.99
    print(age, name, price)
    

    Bây giờ age chứa 17. Sử dụng tên biến ở bất cứ đâu bạn cần giá trị, và thay đổi nó sau này:

    age = 17
    age = age + 1   # age is now 18
    print(age)
    
    A variable is a name attached to a stored value
    Mỗi tên biến trỏ đến một giá trị trong bộ nhớ
    • Dấu = không có nghĩa là "bằng". Nó có nghĩa là "lưu giá trị vế phải dưới tên vế trái".
    • Để kiểm tra xem hai giá trị có bằng nhau hay không, hãy sử dụng == (xem phần dưới).
    2.2

    Số: int & float

    English

    Python has two main number types. An integer 整数 (int) is a whole number like 17. A float 浮点数 (float) has a decimal point like 9.99.

    These operators 运算符 work on numbers:

    Operator Meaning Example Result
    + add 3 + 2 5
    - subtract 3 - 2 1
    * multiply 3 * 2 6
    / divide (always float) 7 / 2 3.5
    // integer divide 7 // 2 3
    % remainder (modulo) 7 % 2 1
    ** power 2 ** 3 8
    • / always gives a float, so 4 / 2 is 2.0.
    • // and % go together: 17 // 5 is 3, and 17 % 5 is 2.
    Tiếng Việt

    Python có hai loại số chính. Số nguyên (int) là một số nguyên như 17. Số thập phân (float) có dấu phẩy thập phân như 9.99.

    Các toán tử sau hoạt động trên các con số:

    Toán tử Ý nghĩa Ví dụ Kết quả
    + cộng 3 + 2 5
    - trừ 3 - 2 1
    * nhân 3 * 2 6
    / chia (luôn là số thập phân) 7 / 2 3.5
    // chia lấy phần nguyên 7 // 2 3
    % phần dư (modulo) 7 % 2 1
    ** lũy thừa 2 ** 3 8
    • / luôn trả về số thập phân, vì vậy 4 / 2 là 2.0.
    • // và % đi kèm với nhau: 17 // 5 là 3, và 17 % 5 là 2.
    2.3

    Biểu thức & chuyển đổi kiểu

    English

    An expression 表达式 is anything that has a value, like 3 + 4 * 2. Python uses normal maths order (* and / before + and -); add brackets to make the order clear.

    input() gives a string, so convert it before doing maths. Changing a value from one type to another is type conversion 类型转换:

    • int("abc") fails, so only convert text that looks like a number.
    • Mixing types fails too: "age: " + 17 is an error; write "age: " + str(17).
    Tiếng Việt

    Một biểu thức là bất cứ thứ gì có giá trị, ví dụ như 3 + 4 * 2. Python tuân theo thứ tự toán học thông thường (* và / thực hiện trước + và -); hãy thêm ngoặc đơn để làm rõ thứ tự.

    input() trả về chuỗi, vì vậy hãy chuyển đổi nó trước khi thực hiện phép tính. Thay đổi giá trị từ kiểu này sang kiểu khác được gọi là chuyển đổi kiểu:

    age = int("17")        # text "17" -> number 17
    price = float("9.99")  # text -> 9.99
    label = str(17)        # number -> text "17"
    print(age, price, label)
    
    • int("abc") thất bại, vì vậy chỉ chuyển đổi văn bản trông giống như số.
    • Trộn lẫn các kiểu cũng sẽ thất bại: "age: " + 17 là lỗi; hãy viết "age: " + str(17).
    2.4

    Giá trị logic & So sánh

    English

    A Boolean 布尔值 is one of just two values: True or False. A comparison 比较 gives back a Boolean.

    Operator Meaning
    == equal to
    != not equal to
    < > less than / greater than
    <= >= less / greater than or equal to

    Join comparisons with and, or, not:

    Common mistakes

    • / always gives a float, even 4 / 2 is 2.0. Use // when you want a whole number.
    • Using = where you mean ==: = assigns a value, == tests whether two values are equal.
    • Joining a string and a number: "age: " + 5 raises a TypeError. Convert first with str(5).
    • Floats are not exact, so 0.1 + 0.2 is not exactly 0.3 — avoid == on float results.
    Tiếng Việt

    Một布尔值 (Boolean) chỉ có hai giá trị: True hoặc False. Một phép so sánh sẽ trả về布尔值 (Boolean).

    Toán tử Ý nghĩa
    == bằng với
    != khác với
    < > nhỏ hơn / lớn hơn
    <= >= nhỏ hơn / lớn hơn hoặc bằng
    print(7 > 2)        # True
    print(3 == 3.0)     # True
    age = 20
    print(age >= 18)    # True
    

    Nối các phép so sánh với and, or, not:

    age = 20
    print(age >= 13 and age <= 19)   # True only for a teenager
    

    Lỗi thường gặp

    • / luôn trả về số thập phân, ngay cả khi 4 / 2 là 2.0. Hãy sử dụng // khi bạn muốn số nguyên.
    • Sử dụng = nơi bạn có ý định là ==: = gán giá trị, == kiểm tra xem hai giá trị có bằng nhau hay không.
    • Ghép chuỗi và số: "age: " + 5 gây ra lỗi TypeError. Hãy chuyển đổi trước bằng str(5).
    • Số thập phân không chính xác tuyệt đối, vì vậy 0.1 + 0.2 không hoàn toàn bằng 0.3 — tránh == trên kết quả số thập phân.
  • 3 Strings · ⁨Chuỗi ký tự⁩
    3.1

    Chỉ mục

    English

    A string 字符串 is text inside quotes. Each character 字符 has a position, called its index 索引. The first index is 0, not 1.

    Read one character with square brackets:

    • Counting starts at 0, so the last index is len(word) - 1.
    • A negative index counts back from the end: word[-1] is the last character.
    • An index that is too large gives an error 错误 (an IndexError).
    Tiếng Việt

    Một chuỗi là văn bản nằm trong dấu ngoặc kép. Mỗi ký tự đều có vị trí, được gọi là chỉ mục. Chỉ mục đầu tiên là 0, không phải 1.

    Đọc một ký tự với ngoặc vuông:

    word = "Python"
    print(word[0])    # P  (the first character)
    print(word[2])    # t
    print(len(word))  # 6  (how many characters)
    
    • Đếm bắt đầu từ 0, vì vậy chỉ mục cuối cùng là len(word) - 1.
    • Chỉ số âm đếm ngược từ cuối: word[-1] là ký tự cuối cùng.
    word = "Python"
    print(word[-1])   # n
    print(word[-2])   # o
    
    • Một chỉ mục quá lớn sẽ gây ra lỗi (một lỗi IndexError).
    s[start:stop] is a half-open window of characters
    s[start:stop] là cửa sổ mở một nửa các ký tự
    3.2

    Cắt chuỗi (Slicing)

    English

    A slice 切片 takes a part of a string. Write word[start:end]. The slice keeps start but stops before end.

    • Leave out start to begin at 0; leave out end to go to the end.
    • A third number is the step 步长. word[::-1] reverses 反转 the string.
    Tiếng Việt

    Cắt chuỗi lấy một phần của chuỗi. Viết word[start:end]. Phần cắt giữ start nhưng dừng lại trước end.

    word = "Python"
    print(word[0:3])   # Pyt   (positions 0, 1, 2)
    print(word[2:5])   # tho
    
    • Bỏ qua start để bắt đầu từ 0; bỏ qua end để đi đến cuối.
    word = "Python"
    print(word[:3])    # Pyt
    print(word[3:])    # hon
    
    • Một số thứ ba là bước nhảy. word[::-1] đảo ngược chuỗi.
    print("Python"[::-1])   # nohtyP
    
    3.3

    Phương thức chuỗi & độ dài

    English

    A method 方法 is a function that belongs to a value. You call it with a dot:

    Strings are immutable 不可变: a method returns a new string and never changes the original 原始 one.

    Common methods (each returns a new value):

    Method Meaning Example Result
    .upper() / .lower() change case "Hi".lower() hi
    .strip() remove edge spaces " hi ".strip() hi
    .replace(a, b) swap text "cat".replace("c", "b") bat
    .split(sep) break into a list "a,b".split(",") ['a', 'b']

    Join strings with +. This is called concatenation 拼接:

    Tiếng Việt

    Một phương thức là một hàm thuộc về một giá trị. Bạn gọi nó bằng dấu chấm:

    name = "mei chen"
    print(name.upper())     # MEI CHEN
    print(name.title())     # Mei Chen
    print(len(name))        # 8
    

    Chuỗi không thể thay đổi tại chỗ: một phương thức trả về chuỗi mới và không bao giờ thay đổi chuỗi gốc.

    name = "mei"
    print(name.upper())     # MEI  (the returned value)
    print(name)             # mei  (the original is unchanged)
    

    Các phương thức phổ biến (mỗi cái trả về một giá trị mới):

    Phương thức Ý nghĩa Ví dụ Kết quả
    .upper() / .lower() thay đổi chữ hoa/thường "Hi".lower() hi
    .strip() xóa khoảng trắng ở cạnh " hi ".strip() hi
    .replace(a, b) hoán đổi chữ hoa/thường "cat".replace("c", "b") bat
    .split(sep) tách thành danh sách "a,b".split(",") ['a', 'b']

    Ghép chuỗi với +. Điều này được gọi là nối chuỗi:

    first = "Mei"
    last = "Chen"
    print(first + " " + last)   # Mei Chen
    
    3.4

    f-strings

    English

    An f-string 格式化字符串 builds text from values. Put f before the quote, then write {...} around a value.

    • Any expression 表达式 can go inside the braces.
    • {value:.2f} rounds to 2 decimal places 小数位.

    Common mistakes

    • Strings cannot be changed in place: s[0] = "x" raises an error. Build a new string instead.
    • Indexing starts at 0; the last character is s[-1], and s[len(s)] is out of range.
    • A slice s[a:b] includes a but stops before b.
    • String methods return a NEW string: s.upper() does nothing unless you store the result.
    Tiếng Việt

    f-string xây dựng văn bản từ các giá trị. Đặt f trước dấu ngoặc kép, sau đó viết {...} quanh một giá trị.

    name = "Mei"
    age = 17
    print(f"{name} is {age} years old")   # Mei is 17 years old
    
    • Bất kỳ biểu thức nào cũng có thể đặt trong dấu ngoặc nhọn.
    • {value:.2f} làm tròn đến 2 chữ số thập phân.
    price = 9.5
    print(f"Two cost {price * 2}")        # Two cost 19.0
    print(f"Pi is about {3.14159:.2f}")   # Pi is about 3.14
    

    Lỗi thường gặp

    • Chuỗi không thể thay đổi tại chỗ: s[0] = "x" gây ra lỗi. Hãy xây dựng chuỗi mới thay thế.
    • Chỉ số bắt đầu từ 0; ký tự cuối cùng là s[-1], và s[len(s)] nằm ngoài phạm vi hợp lệ.
    • Một phần cắt s[a:b] bao gồm a nhưng dừng lại trước b.
    • Các phương thức chuỗi trả về MỘT CHUỖI MỚI: s.upper() không làm gì cả trừ khi bạn lưu kết quả.
  • 4 Selection · ⁨Sự lựa chọn⁩
    4.1

    if / elif / else

    English

    A program chooses what to do with if. It runs an indented 缩进 block only when a condition 条件 is true. The if line ends with a colon 冒号.

    Add elif (else-if) for more cases and else for "anything else". Python runs the first true branch 分支 only, then skips the rest.

    • Compare values with == (equal to), != (not equal to), <, >, <=, >=.
    • A comparison 比较 gives a Boolean 布尔值 — either True or False.
    Tiếng Việt

    Một chương trình chọn thực hiện if. Nó chạy một khối thụt vào trong chỉ khi điều kiện là đúng. Dòng if kết thúc bằng dấu hai chấm.

    score = 72
    if score >= 60:
        print("pass")
    # pass
    

    Thêm elif (else-if) cho nhiều trường hợp hơn và else cho "bất cứ điều gì khác". Python chỉ thực thi nhánh đầu tiên đúng, sau đó bỏ qua phần còn lại.

    score = 72
    if score >= 80:
        print("A")
    elif score >= 60:
        print("B")
    else:
        print("fail")
    # B
    
    • So sánh giá trị với == (bằng), != (khác), <, >, <=, >=.
    • Một phép so sánh trả về giá trị Boolean — hoặc True hoặc False.
    if / elif / else: chỉ một nhánh được thực thi
    if / elif / else: chỉ một nhánh được thực thi
    4.2

    Kết hợp các điều kiện

    English

    Join conditions with and, or, not. and needs both sides true; or needs either side true; not flips a Boolean.

    • Use brackets to make the order clear: (a or b) and c.

    Common mistakes

    • Write elif, not else if.
    • Every if / elif / else line ends with a colon :, and its body must be indented.
    • if x = 5: is an error — use == to compare.
    • else takes no condition; only if and elif do.
    Tiếng Việt

    Nối các điều kiện bằng and, or, not. and cần cả hai vế đều đúng; or cần một trong hai vế đúng; not đảo ngược giá trị Boolean.

    age = 16
    has_ticket = True
    if age >= 18 and has_ticket:
        print("entry allowed")
    else:
        print("entry refused")
    # entry refused
    
    • Sử dụng ngoặc đơn để làm rõ thứ tự: (a or b) and c.
    temp = 30
    if temp > 25 and not temp > 35:
        print("warm but ok")
    # warm but ok
    

    Lỗi thường gặp

    • Viết elif, không phải else if.
    • Mỗi dòng if / elif / else đều kết thúc bằng dấu hai chấm :, và thân của nó phải được thụt vào trong.
    • if x = 5: là lỗi — hãy dùng == để so sánh.
    • else không nhận điều kiện; chỉ có if và elif mới làm được.
  • 5 Iteration · ⁨Lặp lại⁩
    5.1

    Vòng lặp for và range

    English

    A loop 循环 repeats code. A for loop repeats once for each item in a sequence 序列. range(n) gives the numbers 0 up to n - 1.

    • range(a, b) goes from a up to (but not including) b.
    • range(a, b, step) adds a step 步长 each time.
    Tiếng Việt

    Vòng lặp thực thi lặp lại mã. Một vòng lặp for sẽ lặp lại một lần cho mỗi phần tử trong một dãy. range(n) tạo ra các số từ 0 đến n - 1.

    for i in range(5):
        print(i)
    # 0, then 1, 2, 3, 4 (each on its own line)
    
    • range(a, b) đi từ a lên (nhưng không bao gồm) b.
    • range(a, b, step) thêm một bước nhảy mỗi lần.
    for n in range(2, 11, 2):
        print(n)        # 2 4 6 8 10
    
    for i in range(n): thân vòng lặp chạy với i = 0 … n-1
    for i in range(n): thân vòng lặp chạy với i = 0 … n-1
    5.2

    Mẫu bộ tích lũy

    English

    To build a result across a loop, start a variable before the loop, then update 更新 it each turn. This is the accumulator 累加器 pattern.

    • The same idea counts how many items match a test.
    Tiếng Việt

    Để xây dựng kết quả qua vòng lặp, khởi tạo một biến trước vòng lặp, sau đó cập nhật nó mỗi lượt. Đây là mẫu bộ tích lũy.

    total = 0
    for n in range(1, 6):
        total = total + n
    print(total)        # 15
    
    • Ý tưởng tương tự cũng đếm số lượng mục khớp với kiểm tra.
    count = 0
    for letter in "banana":
        if letter == "a":
            count = count + 1
    print(count)        # 3
    
    5.3

    Vòng lặp while

    English

    A while loop repeats as long as a condition stays true. Change something inside, or it never stops — an infinite loop 无限循环.

    • break leaves the loop straight away.
    Tiếng Việt

    Một vòng lặp while lặp lại miễn là điều kiện vẫn đúng. Thay đổi gì đó bên trong, nếu không nó sẽ không bao giờ dừng lại — vòng lặp vô hạn.

    n = 1
    while n <= 3:
        print(n)
        n = n + 1
    # 1 2 3
    
    • break thoát khỏi vòng lặp ngay lập tức.
    total = 0
    while True:
        total = total + 10
        if total >= 30:
            break
    print(total)        # 30
    
    5.4

    Vòng lặp lồng nhau

    English

    A loop inside another loop is a nested loop 嵌套循环. The inner loop 内层循环 runs fully for each turn of the outer loop 外层循环.

    Common mistakes

    • range(n) goes from 0 to n - 1, not 1 to n — the classic off-by-one error.
    • Changing a list while looping over it skips items; loop over a copy if you must remove things.
    • Forgetting to change the loop variable in a while makes it run forever.
    • Indentation decides what is inside the loop; a wrongly-indented line runs only once, after the loop.
    Tiếng Việt

    Một vòng lặp nằm trong một vòng lặp khác là vòng lặp lồng nhau. Vòng lặp bên trong chạy trọn vẹn cho mỗi lượt của vòng lặp ngoài.

    for row in range(3):
        line = ""
        for col in range(3):
            line = line + "*"
        print(line)
    # ***
    # ***
    # ***
    

    Lỗi thường gặp

    • range(n) đi từ 0 đến n - 1, không phải từ 1 đến n — đây là lỗi off-by-one kinh điển.
    • Thay đổi danh sách trong khi duyệt qua nó sẽ bỏ sót các mục; hãy duyệt qua bản sao nếu bạn bắt buộc phải xóa những thứ gì đó.
    • Unquên thay đổi biến vòng lặp trong một while khiến nó chạy mãi mãi.
    • Thụt vào trong quyết định cái gì nằm trong vòng lặp; một dòng bị thụt sai sẽ chỉ chạy một lần, sau khi vòng lặp kết thúc.
  • 6 Lists & 2-D lists · ⁨List & list 2-D⁩
    6.1

    Danh sách

    English

    A list 列表 holds many values in order, inside []. Each item 元素 has an index (from 0).

    • Change an item by its index: scores[1] = 100.
    • A list can grow and shrink; a string cannot.

    The everyday list tools:

    Tool Does
    a.append(x) adds x at the end
    a.insert(i, x) inserts x at position i
    a.remove(x) removes the first x
    a.pop() / a.pop(i) removes and returns the last item / item i
    a.sort() sorts the list in place
    sorted(a) returns a NEW sorted list
    x in a is x in the list?
    len(a), sum(a), max(a), min(a) size and quick maths
    Tiếng Việt

    Một danh sách chứa nhiều giá trị theo thứ tự, bên trong []. Mỗi mục có một chỉ số (từ 0).

    scores = [88, 71, 95]
    print(scores[0])      # 88
    print(len(scores))    # 3
    scores.append(60)     # add to the end
    print(scores)         # [88, 71, 95, 60]
    
    • Thay đổi một mục bằng chỉ số của nó: scores[1] = 100.
    • Một danh sách có thể tăng và giảm; một chuỗi ký tự thì không.

    Các công cụ danh sách thông thường:

    Công cụ Tác dụng
    a.append(x) thêm x vào cuối
    a.insert(i, x) chèn x tại vị trí i
    a.remove(x) xóa mục x đầu tiên
    a.pop() / a.pop(i) xóa và trả về phần tử cuối cùng / phần tử i
    a.sort() sắp xếp danh sách tại chỗ
    sorted(a) trả về một DANH SÁCH MỚI đã sắp xếp
    x in a có phải là x trong danh sách?
    len(a), sum(a), max(a), min(a) kích thước và toán học nhanh
    Chỉ mục của danh sách bắt đầu từ 0
    Chỉ số của danh sách bắt đầu từ 0
    6.2

    Duyệt qua một danh sách

    English

    To traverse 遍历 a list is to visit each item. A for loop does this with no index needed.

    • Use enumerate when you also need the index.
    Tiếng Việt

    Duyệt qua một danh sách nghĩa là ghé thăm từng mục. Một vòng lặp for làm điều này mà không cần chỉ số.

    scores = [88, 71, 95]
    total = 0
    for s in scores:
        total = total + s
    print(total)          # 254
    
    • Dùng enumerate khi bạn cũng cần cả chỉ số.
    for i, name in enumerate(["a", "b"]):
        print(i, name)    # 0 a  /  1 b
    
    6.3

    Danh sách 2 chiều (lưới ô)

    English

    A 2-D list 二维列表 is a list of lists — a grid 网格 of rows and columns. Use two indexes: grid[row][col].

    • A nested loop 嵌套循环 visits every cell.
    Tiếng Việt

    Một danh sách 2 chiều là một danh sách chứa các danh sách — một lưới gồm các hàng và cột. Sử dụng hai chỉ số: grid[row][col].

    grid = [[1, 2, 3],
            [4, 5, 6]]
    print(grid[0][2])     # 3
    print(grid[1][0])     # 4
    
    • Một vòng lặp lồng nhau ghé thăm mọi ô.
    grid = [[1, 2], [3, 4]]
    for row in grid:
        for value in row:
            print(value, end=" ")
    print()               # 1 2 3 4
    
    6.4

    comprehension của danh sách

    English

    A list comprehension 列表推导式 builds a new list in one line: [expression for item in sequence].

    • Add if to keep only some items.
    Tiếng Việt

    Comprehension của danh sách xây dựng một danh sách mới trong một dòng: [expression for item in sequence].

    squares = [x * x for x in range(5)]
    print(squares)        # [0, 1, 4, 9, 16]
    
    • Thêm if để giữ lại chỉ một số mục.
    evens = [n for n in range(10) if n % 2 == 0]
    print(evens)          # [0, 2, 4, 6, 8]
    
    6.5

    Tuple & tập hợp

    English

    A tuple 元组 is a fixed sequence in round brackets. It cannot be changed after it is made — use one for values that belong together, and unpack 解包 it into names.

    A function that needs to hand back two results returns a tuple:

    A set 集合 stores each value once, with no order. It is perfect for removing duplicates and for fast membership tests 成员测试.

    Common mistakes

    • b = a does not copy a list: both names point to the same list, so changing one changes the other. Use a.copy() or a[:].
    • The last item is a[-1]; a[len(a)] is out of range.
    • append adds ONE item; use extend or + to join another list.
    • Building a grid with [[0]*3]*3 makes three copies of the same row. Build the rows in a loop instead.
    • A tuple with one item needs a comma: (5,), not (5).
    • A set has no order and no duplicates, so you cannot index it with s[0].
    Tiếng Việt

    Tuple là một dãy cố định trong ngoặc tròn. Nó không thể bị thay đổi sau khi được tạo — hãy dùng nó cho các giá trị thuộc về nhau, và giải nén nó thành các tên riêng.

    point = (3, 4)
    x, y = point            # unpacking
    print(x, y)             # 3 4
    

    Một hàm cần trả về hai kết quả sẽ trả về một tuple:

    def min_max(nums):
        return min(nums), max(nums)
    
    lo, hi = min_max([5, 2, 9])
    print(lo, hi)           # 2 9
    

    Một tập hợp lưu trữ mỗi giá trị chỉ một lần, không có thứ tự. Nó hoàn hảo để loại bỏ trùng lặp và kiểm tra thành viên nhanh chóng.

    votes = ["red", "blue", "red", "green", "red"]
    colours = set(votes)
    print(len(colours))         # 3  (duplicates removed)
    print("blue" in colours)    # True
    

    Lỗi thường gặp

    • b = a không sao chép danh sách: cả hai tên đều trỏ đến cùng một danh sách, nên thay đổi cái này sẽ làm thay đổi cái kia. Hãy dùng a.copy() hoặc a[:].
    • Mục cuối cùng là a[-1]; a[len(a)] nằm ngoài phạm vi.
    • append thêm MỘT mục; hãy dùng extend hoặc + để nối một danh sách khác.
    • Xây dựng lưới với [[0]*3]*3 sẽ tạo ba bản sao của cùng một hàng. Hãy xây dựng các hàng trong vòng lặp thay thế.
    • Tuple có một phần tử cần dấu phẩy: (5,), không phải (5).
    • Tập hợp không có thứ tự và không có trùng lặp, nên bạn không thể dùng chỉ số như s[0] để truy cập.
  • 7 Dictionaries · ⁨Dictionary⁩
    7.1

    Từ điển

    English

    A dictionary 字典 (dict) stores key 键 → value 值 pairs. You look up a value by its key, not by a number index.

    Add and update

    Assign to a key to add it, or to change an existing one.

    Check and loop

    Use in to test for a key. Loop over the keys, or over .items() to get both key and value.

    • .get(key, default) returns a default 默认值 when the key is missing — no error.

    The classic exam pattern — tally how often each value appears:

    • .get(letter, 0) supplies 0 the first time a key is seen, so there is no KeyError.

    Common mistakes

    • Reading a missing key with d[key] raises a KeyError; use d.get(key) or test if key in d first.
    • Assigning d[key] again overwrites the old value — keys are unique.
    • Keys must be immutable, such as a string or number — a list cannot be a key.
    Tiếng Việt

    Từ điển (dict) lưu trữ các cặp khóa → giá trị. Bạn tìm kiếm giá trị theo khóa của nó, không phải theo chỉ số số.

    student = {"name": "Mei", "score": 88}
    print(student["name"])     # Mei
    print(student["score"])    # 88
    

    Thêm và cập nhật

    Gán cho một khóa để thêm vào, hoặc để thay đổi một khóa đã tồn tại.

    student = {"name": "Mei"}
    student["score"] = 88      # add a new key
    student["score"] = 90      # update the value
    print(student)             # {'name': 'Mei', 'score': 90}
    

    Kiểm tra và lặp

    Dùng in để kiểm tra sự tồn tại của một khóa. Lặp qua các khóa, hoặc lặp qua .items() để lấy cả khóa lẫn giá trị.

    student = {"name": "Mei", "score": 90}
    print("score" in student)  # True
    for key, value in student.items():
        print(key, "=", value)
    # name = Mei
    # score = 90
    
    • .get(key, default) trả về giá trị mặc định khi khóa bị thiếu — không gây lỗi.
    student = {"name": "Mei"}
    print(student.get("age", 0))   # 0
    

    Mẫu đề thi kinh điển — đếm xem mỗi giá trị xuất hiện bao nhiêu lần:

    word = "banana"
    counts = {}
    for letter in word:
        counts[letter] = counts.get(letter, 0) + 1
    print(counts)   # {'b': 1, 'a': 3, 'n': 2}
    
    • .get(letter, 0) cung cấp 0 lần đầu tiên khi gặp một khóa, vì vậy sẽ không có KeyError.

    Lỗi thường gặp

    • Đọc một khóa bị thiếu bằng d[key] sẽ gây ra KeyError; hãy dùng d.get(key) hoặc kiểm tra if key in d trước.
    • Gán lại d[key] sẽ ghi đè giá trị cũ — các khóa phải duy nhất.
    • Khóa phải là bất biến, chẳng hạn như chuỗi ký tự hoặc số — danh sách không thể là khóa.
    Từ điển ánh xạ mỗi khóa với một giá trị
    Từ điển ánh xạ mỗi khóa với một giá trị
  • 8 Functions & abstraction · ⁨Hàm & trừu tượng hóa⁩
    8.1

    Định nghĩa & gọi hàm

    English

    A function 函数 is a named block of code you can reuse. Define 定义 it with def, then call 调用 it by name.

    • The code inside runs only when you call the function.
    Tiếng Việt

    Hàm là một khối mã code có tên mà bạn có thể tái sử dụng. Định nghĩa nó bằng def, sau đó gọi nó bằng tên.

    def greet():
        print("Hello!")
    
    greet()        # Hello!
    greet()        # Hello!
    
    • Mã code bên trong chỉ chạy khi bạn gọi hàm.
    def định nghĩa; call chạy; return gửi giá trị trở lại
    def định nghĩa; call thực thi; return gửi lại một giá trị
    8.2

    Trả về giá trị

    English

    A function can return 返回 a value with return. The call then stands for that value.

    • return ends the function at once. A function with no return gives None.
    Tiếng Việt

    Hàm có thể trả về một giá trị bằng return. Khi đó, lời gọi hàm sẽ đại diện cho giá trị đó.

    def square(n):
        return n * n
    
    print(square(5))          # 25
    print(square(3) + 1)      # 10
    
    • return kết thúc hàm ngay lập tức. Một hàm không có return sẽ trả về None.
    8.3

    Tham số, đối số & phạm vi

    English

    A parameter 形参 is the name in the def. An argument 实参 is the value you pass in.

    A variable made inside a function is local 局部 — it exists only there. That region is its scope 作用域.

    A parameter can have a default value 默认值, used when the caller leaves it out:

    Tiếng Việt

    Tham số là tên trong def. Đối số là giá trị bạn truyền vào.

    def power(base, exp):         # base, exp are parameters
        return base ** exp
    
    print(power(2, 3))            # 8  (2 and 3 are arguments)
    

    Biến được tạo bên trong hàm là biến cục bộ — nó chỉ tồn tại ở đó. Khu vực đó chính là phạm vi của nó.

    def f():
        x = 10            # local to f
        return x
    
    print(f())            # 10
    # print(x) here would be an error: x is not defined outside f
    

    Tham số có thể có giá trị mặc định, được sử dụng khi người gọi bỏ qua:

    def greet(name, greeting="Hello"):
        return greeting + ", " + name
    
    print(greet("Mei"))              # Hello, Mei
    print(greet("Sam", "Welcome"))   # Welcome, Sam
    
    8.4

    Trừu tượng hóa thủ tục

    English

    Procedural abstraction 过程抽象 means hiding details behind a name. You use a function by its name and what it does, not by how it works.

    • A good function does one job, has a clear name, and avoids repeating code.
    Tiếng Việt

    Trừ抽象 hóa thủ tục có nghĩa là che giấu chi tiết behind a name. Bạn sử dụng hàm bằng tên và chức năng của nó, chứ không phải cách thức hoạt động.

    def area_of_rectangle(w, h):
        return w * h
    
    print(area_of_rectangle(4, 5))   # 20
    
    • Một hàm tốt làm một việc, có tên rõ ràng, và tránh lặp lại mã.
    8.5

    Mô-đun & import

    English

    A module 模块 is a file of ready-made functions. Bring one in with import 导入.

    Common mistakes

    • A function returns None unless you write return. Printing is not the same as returning.
    • Never use a mutable default like def f(x=[]) — the same list is shared between all calls.
    • A variable made inside a function is local and cannot be seen outside it.
    • Run a function with f(); writing f on its own only names it.
    Tiếng Việt

    Một mô-đun là tập tin chứa các hàm sẵn có. Hãy đưa vào bằng import.

    import random
    random.seed(0)               # makes the result repeatable
    print(random.randint(1, 6))  # a dice roll
    
    import math
    print(math.sqrt(16))         # 4.0
    

    Lỗi thường gặp

    • Hàm sẽ trả về None trừ khi bạn viết return. In ra không giống với việc trả về.
    • Không bao giờ dùng mặc định có thể thay đổi như def f(x=[]) — cùng danh sách đó được chia sẻ giữa tất cả các lần gọi.
    • Biến được tạo bên trong hàm là cục bộ và không thể nhìn thấy từ bên ngoài.
    • Chạy hàm với f(); việc viết f đơn thuần chỉ đặt tên cho nó.
  • 9 Errors, exceptions & testing · ⁨Lỗi, ngoại lệ & kiểm thử⁩
    9.1

    Lỗi & gỡ lỗi

    English

    Code can fail in three ways. A syntax error 语法错误 breaks Python's rules, so it never runs. A runtime error 运行时错误 happens while running, like dividing by zero. A logic error 逻辑错误 runs but gives the wrong answer.

    • Python prints a traceback 回溯 showing where it failed. Read it from the bottom up.
    Tiếng Việt

    Mã có thể thất bại theo ba cách. Lỗi cú pháp vi phạm quy tắc của Python, nên nó không bao giờ chạy. Lỗi thời gian chạy xảy ra khi đang chạy, ví dụ như chia cho 0. Lỗi logic chạy nhưng trả về kết quả sai.

    # A runtime error, caught so this block still finishes:
    try:
        print(10 / 0)
    except ZeroDivisionError:
        print("cannot divide by zero")
    # cannot divide by zero
    
    • Python in ra traceback hiển thị nơi nó thất bại. Đọc từ dưới lên trên.
    Các lỗi Python phổ biến: Cú pháp, Tên, Kiểu, Chỉ mục
    Các lỗi Python phổ biến: Cú pháp, Tên, Kiểu, Chỉ mục
    9.2

    try / except / raise

    English

    Wrap risky code in try. If it fails, except catches the exception 异常 and handles 处理 it, instead of crashing.

    • Catch a specific type (ValueError, ZeroDivisionError, …).
    • raise makes your own error on purpose.
    Tiếng Việt

    Bọc mã rủi ro trong try. Nếu thất bại, except bắt ngoại lệ và xử lý nó, thay vì bị sập.

    def to_int(text):
        try:
            return int(text)
        except ValueError:
            return 0
    
    print(to_int("42"))    # 42
    print(to_int("abc"))   # 0
    
    • Bắt một loại cụ thể (ValueError, ZeroDivisionError, …).
    • raise tạo ra lỗi của riêng bạn một cách chủ ý.
    def set_age(age):
        if age < 0:
            raise ValueError("age cannot be negative")
        return age
    
    try:
        set_age(-1)
    except ValueError as err:
        print("error:", err)
    # error: age cannot be negative
    
    9.3

    Kiểm thử & độ bền

    English

    A test 测试 checks that code gives the right answer. Try normal cases and edge cases 边界情形 — empty input, zero, very large values.

    • Robust 健壮 code does not crash on strange input; it handles it gracefully.

    Common mistakes

    • Do not use a bare except: — catch the specific error, e.g. except ValueError:.
    • A syntax error stops the whole program before it runs, so fix those first.
    • Test the edge cases (empty input, zero, the largest value), not just the easy one.
    Tiếng Việt

    Kiểm thử xác nhận rằng mã trả về đáp án đúng. Thử các trường hợp bình thường và trường hợp biên — đầu vào rỗng, số 0, giá trị rất lớn.

    def average(nums):
        if len(nums) == 0:        # edge case: empty list
            return 0
        return sum(nums) / len(nums)
    
    print(average([2, 4, 6]))     # 4.0
    print(average([]))            # 0
    
    • Mã bền vững không bị sập trước đầu vào kỳ lạ; nó xử lý nó một cách thanh lịch.

    Lỗi thường gặp

    • Không dùng bare except: — hãy bắt lỗi cụ thể, ví dụ except ValueError:.
    • Lỗi cú pháp dừng toàn bộ chương trình trước khi chạy, nên sửa những lỗi đó trước.
    • Kiểm thử các trường hợp biên (đầu vào rỗng, số 0, giá trị lớn nhất), không chỉ trường hợp dễ.
  • 10 Files · ⁨Tệp tin⁩
    10.1

    Đọc & ghi tập tin văn bản

    English

    A text file 文本文件 stores text on disk. Open it with open(name, mode) where mode 模式 says read or write. Always use with, which closes the file for you.

    Writing

    Mode "w" writes a new file and erases any old one.

    Reading

    Mode "r" (the default) reads. .read() returns the whole file as one string.

    Line by line

    Loop over the file to get one line at a time. .strip() removes 去除 the newline 换行符 at the end.

    Appending

    Mode "a" appends 追加 — it adds to the end without erasing.

    Mode Meaning
    "r" read (default)
    "w" write (erases first)
    "a" append (add to the end)

    Common mistakes

    • Always close a file, or use with open(...) as f: which closes it for you.
    • read() gives the whole file as one string, and each line still ends with \n.
    • Opening with "w" erases the file first; use "a" to add to the end.
    Tiếng Việt

    Tập tin văn bản lưu trữ văn bản trên ổ đĩa. Mở nó với open(name, mode) nơi mode chỉ định đọc hoặc ghi. Luôn dùng with, đóng tập tin cho bạn.

    Ghi

    Mode "w" ghi một tập tin mới và xóa bất kỳ tập tin cũ nào.

    with open("notes.txt", "w") as f:
        f.write("first line\n")
        f.write("second line\n")
    print("saved")            # saved
    

    Đọc

    Mode "r" (mặc định) đọc. .read() trả về toàn bộ tập tin như một chuỗi duy nhất.

    with open("notes.txt", "w") as f:
        f.write("hello\nworld\n")
    with open("notes.txt") as f:
        print(f.read().strip())   # hello / world
    

    Theo dòng

    Lặp qua tệp để lấy từng dòng một. .strip() xóa ký tự xuống dòng ở cuối.

    with open("data.txt", "w") as f:
        f.write("Mei,88\nSam,71\n")
    with open("data.txt") as f:
        for line in f:
            name, score = line.strip().split(",")
            print(name, "scored", score)
    # Mei scored 88
    # Sam scored 71
    

    Ghi thêm

    Mode "a" ghi thêm — nó thêm vào cuối mà không xóa.

    with open("log.txt", "w") as f:
        f.write("line 1\n")
    with open("log.txt", "a") as f:
        f.write("line 2\n")
    with open("log.txt") as f:
        print(f.read().strip())   # line 1 / line 2
    
    Mode Ý nghĩa
    "r" đọc (mặc định)
    "w" ghi (xóa trước)
    "a" ghi thêm (thêm vào cuối)

    Lỗi thường gặp

    • Luôn đóng tập tin, hoặc dùng with open(...) as f: đóng tập tin cho bạn.
    • read() trả về toàn bộ tệp dưới dạng một chuỗi, và mỗi dòng vẫn kết thúc bằng \n.
    • Mở với "w" sẽ xóa tập tin trước; dùng "a" để thêm vào cuối.
    open → đọc/ghi → close (với auto-closes)
    open → đọc/ghi → close (với auto-closes)
  • 11 Algorithm design · ⁨Thiết kế thuật toán⁩
    11.1

    Thuật toán & phân tách

    English

    An algorithm 算法 is a clear list of steps that solves a problem. Decomposition 分解 means breaking a big problem into smaller parts you can solve one at a time.

    • Abstraction 抽象 means ignoring detail: you use largest(...) without re-reading how it works.
    Tiếng Việt

    Thuật toán là danh sách các bước rõ ràng giải quyết một vấn đề. Phân tách có nghĩa là chia nhỏ vấn đề lớn thành các phần nhỏ hơn mà bạn có thể giải quyết từng phần một.

    # Algorithm: find the largest number in a list
    def largest(nums):
        best = nums[0]
        for n in nums:
            if n > best:
                best = n
        return best
    
    print(largest([3, 9, 2, 7]))   # 9
    
    • Trừ抽象 hóa có nghĩa là bỏ qua chi tiết: bạn sử dụng largest(...) mà không cần đọc lại cách nó hoạt động.
    11.2

    Mã giả & sơ đồ luồng

    English

    Pseudocode 伪代码 is plain, structured English for an algorithm, written before the real code. It is not run.

    A flowchart 流程图 draws the same plan: a box for each step, a diamond for each decision 判断, and arrows for the order.

    Tiếng Việt

    伪代码 là tiếng Anh đơn giản, có cấu trúc cho thuật toán, được viết trước mã thật. Nó không được chạy.

    SET best TO first number
    FOR Each number n
        IF n > best
          THEN
            SET best TO n
            OUTPUT best
    

    Sơ đồ khối vẽ cùng kế hoạch đó: ô vuông cho mỗi bước, hình thoi cho mỗi quyết định, và mũi tên cho thứ tự.

    11.3

    Đệ quy & ngăn xếp lời gọi

    English

    Recursion 递归 is when a function calls itself. It needs a base case 基准情形 (a simple input that returns at once) and a recursive case 递归情形 (it calls itself on a smaller input).

    • Each paused call sits on the call stack 调用栈 until the call above it returns.

    Common mistakes

    • Recursion needs a base case, or it calls itself forever and crashes the call stack.
    • Pseudocode is for planning — it need not run, but every step must be unambiguous.
    • Break a big problem into small named steps before you write any code.
    Tiếng Việt

    Đệ quy là khi một hàm gọi chính nó. Nó cần một trường hợp cơ sở (input đơn giản trả về ngay) và trường hợp đệ quy (nó gọi chính nó trên input nhỏ hơn).

    Call stack cho factorial(3): mỗi cuộc gọi chờ đợi, rồi trả về theo thứ tự ngược lại
    Call stack cho factorial(3): mỗi cuộc gọi chờ đợi, rồi trả về theo thứ tự ngược lại
    def fact(n):
        return 1 if n <= 1 else n * fact(n - 1)
    
    print(fact(5))     # 120
    
    • Mỗi lời gọi tạm dừng nằm trên ngăn xếp lời gọi cho đến khi lời gọi phía trên trả về.

    Lỗi thường gặp

    • Đệ quy cần trường hợp cơ sở, nếu không nó sẽ gọi chính nó mãi mãi và làm sập ngăn xếp lời gọi.
    • 伪代码 dành cho lập kế hoạch — nó không cần chạy, nhưng mọi bước đều phải không mơ hồ.
    • Chia nhỏ vấn đề lớn thành các bước nhỏ có tên trước khi viết bất kỳ mã nào.
  • 12 Data structures · ⁨Cấu trúc dữ liệu⁩
    12.1

    Kiểu Dữ Liệu Trừ Tượng (ADT)

    English

    An abstract data type 抽象数据类型 (ADT) describes some data plus the operations on it, separate from how it is built. You use it through its operations, not through its inner storage.

    Tiếng Việt

    Một kiểu dữ liệu trừ抽象化 (ADT) mô tả một số dữ liệu plus các thao tác trên đó, tách biệt khỏi cách xây dựng. Bạn sử dụng nó thông qua các thao tác, không phải qua bộ nhớ lưu trữ bên trong.

    # A stack ADT, built on a list
    s = []
    s.append(1)        # add
    s.append(2)
    print(s.pop())     # 2  (remove the most recent)
    
    12.2

    Ngăn xếp (Stacks)

    English

    A stack 栈 is last-in, first-out (LIFO 后进先出). You push 压入 onto the top and pop 弹出 from the top.

    Tiếng Việt

    Ngăn xếp là last-in, first-out (LIFO). Bạn push lên trên cùng và pop từ trên cùng.

    Ngăn xếp lấy từ trên cùng (LIFO); hàng đợi lấy từ đầu (FIFO)
    Ngăn xếp lấy từ trên cùng (LIFO); hàng đợi lấy từ đầu (FIFO)
    stack = []
    stack.append("a")
    stack.append("b")
    print(stack.pop())   # b
    print(stack.pop())   # a
    
    12.3

    Hàng đợi

    English

    A queue 队列 is first-in, first-out (FIFO 先进先出). You enqueue 入队 at the back and dequeue 出队 from the front.

    Tiếng Việt

    Hàng đợi là first-in, first-out (FIFO). Bạn enqueue ở phía sau và dequeue từ phía trước.

    queue = []
    queue.append("a")     # enqueue
    queue.append("b")
    print(queue.pop(0))   # a  (dequeue the front)
    print(queue.pop(0))   # b
    
    12.4

    Linked lists

    English

    A linked list 链表 is a chain of nodes 节点. Each node holds data and a pointer 指针 to the next node; the last points to None.

    Tiếng Việt

    Danh sách liên kết là chuỗi các nút. Mỗi nút chứa dữ liệu và con trỏ đến nút tiếp theo; nút cuối trỏ về None.

    Danh sách liên kết: mỗi nút chứa dữ liệu và con trỏ đến nút tiếp theo, kết thúc ở None
    Danh sách liên kết: mỗi nút chứa dữ liệu và con trỏ đến nút tiếp theo, kết thúc ở None
    n3 = {"data": 3, "next": None}
    n2 = {"data": 2, "next": n3}
    n1 = {"data": 1, "next": n2}
    node = n1
    while node is not None:      # traverse to the end
        print(node["data"])
        node = node["next"]
    # 1 2 3
    
    12.5

    Bảng băm

    English

    A hash table 哈希表 maps a key to a slot with a hash function 哈希函数. Two keys can land in the same slot — a collision 冲突. Python's dict is a hash table, so lookup is fast.

    Tiếng Việt

    Bảng băm ánh xạ khóa sang một slot bằng hàm băm. Hai khóa có thể rơi vào cùng một slot — va chạm. Python's dict là bảng băm, nên tra cứu rất nhanh.

    Hàm băm ánh xạ mỗi khóa sang một slot; hai khóa có thể va chạm trong một slot
    Hàm hash ánh xạ mỗi khóa vào một ô; hai khóa có thể va chạm trong cùng một ô
    table = {}
    table["Mei"] = 88
    table["Sam"] = 71
    print(table["Mei"])   # 88  (fast lookup by key)
    
    12.6

    Cây tìm kiếm nhị phân

    English

    A binary search tree 二叉搜索树 (BST) keeps order: every left child is smaller than its node, every right child is larger. Search stays fast.

    Tiếng Việt

    Cây tìm kiếm nhị phân (BST) giữ thứ tự: mọi con trái nhỏ hơn node của nó, mọi con phải lớn hơn. Tìm kiếm vẫn nhanh.

    Cây tìm kiếm nhị phân: giá trị nhỏ đi sang trái, giá trị lớn đi sang phải
    Cây tìm kiếm nhị phân: giá trị nhỏ đi sang trái, giá trị lớn đi sang phải
    def insert(root, val):
        if root is None:
            return {"val": val, "left": None, "right": None}
        if val < root["val"]:
            root["left"] = insert(root["left"], val)
        else:
            root["right"] = insert(root["right"], val)
        return root
    
    def inorder(root):
        if root is None:
            return []
        return inorder(root["left"]) + [root["val"]] + inorder(root["right"])
    
    tree = None
    for v in [5, 3, 8, 1, 4]:
        tree = insert(tree, v)
    print(inorder(tree))   # [1, 3, 4, 5, 8]
    
    12.7

    Đồ thị

    English

    A graph 图 is a set of vertices 顶点 joined by edges 边. An adjacency list 邻接表 — a dict of neighbour lists — is a common way to store one.

    Common mistakes

    • A stack is last-in-first-out; a queue is first-in-first-out. Do not mix them up.
    • Check whether a structure is empty before you pop or dequeue from it.
    • In a linked list, losing the head pointer loses the whole list.
    Tiếng Việt

    Đồ thị là tập hợp các đỉnh nối với nhau bằng cạnh. Danh sách kề — một dict chứa danh sách lân cận — là cách phổ biến để lưu trữ một đồ thị.

    Một đồ thị gồm các đỉnh và cạnh, kèm dạng danh sách kề của nó
    Một đồ thị gồm các đỉnh và cạnh, kèm dạng danh sách kề của nó
    graph = {"A": ["B", "D"], "B": ["A", "C"], "C": ["B", "D"], "D": ["A", "C"]}
    for vertex in graph:
        print(vertex, "->", graph[vertex])
    # A -> ['B', 'D']  (and so on for B, C, D)
    

    Lỗi thường gặp

    • Ngăn xếp (stack) là cuối vào trước ra; hàng đợi (queue) là đầu vào trước ra. Đừng nhầm lẫn chúng.
    • Kiểm tra xem cấu trúc có trống không trước khi xóa phần tử từ trên cùng hoặc lấy phần tử ra khỏi hàng đợi.
    • Trong danh sách liên kết, mất con trỏ head sẽ mất cả danh sách.
  • 13 Searching, sorting & efficiency · ⁨Tìm kiếm, sắp xếp & hiệu suất⁩
    13.1

    Linear & binary search

    English

    A search 查找 finds where a value is. Linear search 线性查找 checks each item in turn, so it works on any list.

    Binary search 二分查找 is much faster but needs a sorted list. It halves the range each step.

    Tiếng Việt

    Tìm kiếm là tìm vị trí của một giá trị. Tìm kiếm tuyến tính kiểm tra từng mục theo thứ tự, nên hoạt động trên bất kỳ danh sách nào.

    def linear_search(items, target):
        for i in range(len(items)):
            if items[i] == target:
                return i
        return -1     # not found
    
    print(linear_search([4, 8, 2, 9], 2))   # 2
    

    Tìm kiếm nhị phân nhanh hơn nhiều nhưng cần danh sách đã sắp xếp. Nó thu hẹp phạm vi đi một nửa ở mỗi bước.

    def binary_search(items, target):
        lo, hi = 0, len(items) - 1
        while lo <= hi:
            mid = (lo + hi) // 2
            if items[mid] == target:
                return mid
            elif items[mid] < target:
                lo = mid + 1
            else:
                hi = mid - 1
        return -1
    
    print(binary_search([1, 3, 5, 7, 9], 7))   # 3
    
    Tìm kiếm nhị phân thu hẹp phạm vi đi một nửa ở mỗi bước — O(log n) trên danh sách đã sắp xếp
    Tìm kiếm nhị phân thu hẹp phạm vi đi một nửa ở mỗi bước — O(log n) trên danh sách đã sắp xếp
    13.2

    Sắp xếp (bọt & chèn)

    English

    To sort 排序 is to put items in order. Bubble sort 冒泡排序 repeatedly swaps 交换 neighbours that are in the wrong order.

    Insertion sort 插入排序 builds a sorted part one item at a time, sliding each new item back into its place:

    • In real code, use Python's built-in sorted():
    Tiếng Việt

    Sắp xếp là đặt các mục theo thứ tự. Sắp xếp bọt lặp lại hoán đổi các cặp邻居 bị sai thứ tự.

    def bubble_sort(a):
        a = a[:]                          # work on a copy
        for i in range(len(a)):
            for j in range(len(a) - 1 - i):
                if a[j] > a[j + 1]:
                    a[j], a[j + 1] = a[j + 1], a[j]
        return a
    
    print(bubble_sort([5, 2, 4, 1]))      # [1, 2, 4, 5]
    

    Sắp xếp chèn xây dựng một phần đã sắp xếp từng mục một, trượt mỗi mục mới về đúng vị trí:

    def insertion_sort(a):
        a = a[:]                           # work on a copy
        for i in range(1, len(a)):
            key = a[i]
            j = i - 1
            while j >= 0 and a[j] > key:   # shift bigger values right
                a[j + 1] = a[j]
                j -= 1
            a[j + 1] = key                 # drop key into the gap
        return a
    
    print(insertion_sort([5, 2, 4, 1]))   # [1, 2, 4, 5]
    
    • Trong code thực tế, dùng hàm built-in của Python sorted():
    print(sorted([5, 2, 4, 1]))           # [1, 2, 4, 5]
    
    13.3

    Hiệu suất thuật toán

    English

    Efficiency 效率 asks how the work grows as the input grows. We describe it with Big-O 大O记号.

    Big-O Name Example
    $O(1)$ constant look up a dict key
    $O(\log n)$ logarithmic binary search
    $O(n)$ linear linear search
    $O(n^2)$ quadratic bubble sort
    Tiếng Việt

    Hiệu suất hỏi công việc tăng trưởng như thế nào khi dữ liệu đầu vào tăng. Chúng ta mô tả nó bằng Big-O.

    Cách số bước tăng trưởng theo kích thước đầu vào cho độ phức tạp thường gặp
    Cách số bước tăng trưởng theo kích thước đầu vào cho độ phức tạp thường gặp
    Big-O Tên Ví dụ
    $O(1)$ hằng số tra cứu key của dict
    $O(\log n)$ logarit tìm kiếm nhị phân
    $O(n)$ tuyến tính tìm kiếm tuyến tính
    $O(n^2)$ bậc hai sắp xếp bọt
    def steps(n):           # how many steps a linear scan takes
        count = 0
        for i in range(n):
            count = count + 1
        return count
    
    print(steps(100))       # 100  -> O(n)
    
    13.4

    Ngẫu nhiên & Mô phỏng

    English

    The random module makes random numbers. Use a seed 种子 to make results repeatable. A simulation 模拟 runs many random trials to estimate an answer.

    Common mistakes

    • Binary search only works on a sorted list.
    • Big-O tells you how the time GROWS, not the exact time; an O(n²) method beats O(n) only for tiny inputs.
    • Bubble sort is O(n²) — fine for learning, but slow on large lists.
    Tiếng Việt

    Mô-đun random tạo số ngẫu nhiên. Dùng seed để làm kết quả có thể lặp lại. Một mô phỏng chạy nhiều lần thử ngẫu nhiên để ước lượng câu trả lời.

    import random
    random.seed(0)
    rolls = [random.randint(1, 6) for _ in range(1000)]
    print(rolls.count(6))   # about 1/6 of 1000
    

    Lỗi thường gặp

    • Tìm kiếm nhị phân chỉ hoạt động trên một danh sách đã sắp xếp.
    • Big-O cho bạn biết thời gian TĂNG TRƯỞNG như thế nào, không phải thời gian chính xác; phương pháp O(n²) tốt hơn O(n) chỉ với đầu vào cực nhỏ.
    • Sắp xếp bọt là O(n²) — ổn để học, nhưng chậm trên danh sách lớn.
  • 14 OOP & paradigms · ⁨OOP & paradigm⁩
    14.1

    Lớp & Đối tượng

    English

    A class 类 is a blueprint. An object 对象 is one thing built from it (an instance 实例). __init__ is the constructor 构造方法 that sets up each object; self is the object itself.

    • name is an attribute 属性 (data on the object); speak is a method 方法 (an action).

    Add __str__ to control what print(obj) shows:

    Tiếng Việt

    Lớp là bản thiết kế. Một đối tượng là một thứ được xây dựng từ nó (một instance). __init__ là constructor thiết lập mỗi đối tượng; self là đối tượng đó.

    class Dog:
        def __init__(self, name):
            self.name = name            # an attribute
        def speak(self):
            return self.name + " says woof"
    
    d = Dog("Rex")
    print(d.speak())     # Rex says woof
    
    • name là thuộc tính (dữ liệu trên đối tượng); speak là phương thức (hành động).

    Thêm __str__ để điều khiển những gì print(obj) hiển thị:

    class Dog:
        def __init__(self, name):
            self.name = name
        def __str__(self):
            return f"Dog named {self.name}"
    
    print(Dog("Rex"))    # Dog named Rex
    
    Một lớp là bản thiết kế; gọi nó tạo ra một đối tượng
    Một lớp là bản thiết kế; gọi nó tạo ra một đối tượng
    14.2

    Kế thừa, đóng gói & Đa hình

    English

    Inheritance 继承 lets a subclass 子类 reuse a superclass 父类. Use super() to call the parent; override 重写 a method to change it.

    Encapsulation 封装 hides data behind methods; a leading underscore marks it private 私有.

    Polymorphism 多态 means one name, many behaviours — the right speak runs for each object.

    Tiếng Việt

    Kế thừa cho phép subclass tái sử dụng superclass. Dùng super() để gọi parent; ghi đè phương thức để thay đổi nó.

    class Animal:
        def speak(self):
            return "some sound"
    
    class Cat(Animal):
        def speak(self):                # override
            return "meow"
    
    print(Cat().speak())   # meow
    

    Đóng gói ẩn dữ liệu sau các phương thức; dấu gạch dưới đứng đầu đánh dấu nó là riêng tư.

    class Account:
        def __init__(self):
            self._balance = 0           # private
        def deposit(self, n):
            self._balance += n
        def balance(self):
            return self._balance
    
    a = Account()
    a.deposit(50)
    print(a.balance())     # 50
    

    Đa hình nghĩa là một tên, nhiều hành vi — speak đúng sẽ chạy cho mỗi đối tượng.

    class Cat:
        def speak(self):
            return "meow"
    
    class Cow:
        def speak(self):
            return "moo"
    
    for animal in [Cat(), Cow()]:
        print(animal.speak())   # meow, then moo
    
    14.3

    Các mô hình lập trình

    English

    A paradigm 范式 is a style of writing programs. Procedural 过程式 code is a sequence of steps and functions. Object-oriented 面向对象 code groups data and methods into objects. Declarative 声明式 code says what you want, not how (a list comprehension or SQL).

    Common mistakes

    • Every method needs self as its first parameter.
    • __init__ sets up a new object and runs automatically when you create one.
    • Two objects of the same class have separate attributes; changing one does not change the other.
    Tiếng Việt

    Một paradigm là phong cách viết chương trình. Code thủ tục là chuỗi các bước và hàm. Code hướng đối tượng nhóm dữ liệu và phương thức vào các đối tượng. Code khai báo nói bạn muốn cái gì, không phải làm thế nào (list comprehension hoặc SQL).

    def total(nums):           # procedural
        t = 0
        for n in nums:
            t += n
        return t
    print(total([1, 2, 3]))    # 6
    
    print(sum([1, 2, 3]))      # 6  (declarative: same result)
    

    Lỗi thường gặp

    • Mọi phương thức đều cần self là tham số đầu tiên.
    • __init__ thiết lập một đối tượng mới và chạy tự động khi bạn tạo nó.
    • Hai đối tượng của cùng một lớp có thuộc tính riêng biệt; thay đổi cái này không ảnh hưởng đến cái kia.
  • 15 Data representation · ⁨Biểu diễn dữ liệu⁩
    15.1

    Bit & Nhị phân

    English

    A bit 比特 is a single 0 or 1. Binary 二进制 is the base-2 number system: each place is worth twice the one to its right (1, 2, 4, 8, …). Denary 十进制 (base-10) is our normal numbers.

    • 8 bits make a byte 字节. A fixed width can overflow 溢出 (wrap around) when the number is too big.

    Hexadecimal 十六进制 (base 16) is a compact way to read binary: one hex digit stands for exactly four bits. Python writes hex with 0x:

    Tiếng Việt

    Một bit là một 0 hoặc 1 đơn lẻ. Nhị phân là hệ đếm cơ số 2: mỗi vị trí có giá trị gấp đôi vị trí bên phải (1, 2, 4, 8, …). Thập phân (cơ số 10) là các số bình thường của chúng ta.

    Giá trị vị trí nhị phân: 1101 nghĩa là 8 + 4 + 1 = 13
    Giá trị vị trí nhị phân: 1101 nghĩa là 8 + 4 + 1 = 13
    print(bin(13))         # 0b1101
    print(int("1101", 2))  # 13
    
    • 8 bit tạo thành một byte. Độ rộng cố định có thể tràn (vòng lại) khi số quá lớn.
    x = 250
    x = (x + 10) % 256     # one byte wraps at 256
    print(x)               # 4
    

    Thập lục phân (cơ số 16) là cách gọn gàng để đọc nhị phân: một chữ số thập lục phân đại diện chính xác cho bốn bit. Python viết hex bằng 0x:

    print(hex(255))        # 0xff
    print(0xFF)            # 255
    print(int("ff", 16))   # 255
    
    15.2

    Nén dữ liệu

    English

    Compression 压缩 makes data smaller. Lossless 无损 compression keeps every bit, so you rebuild the original exactly. Lossy 有损 compression throws away detail — smaller but not exact — and is used for photos and music.

    Run-length encoding 游程编码 is a simple lossless method: store a run 游程 (a repeat) as a count plus the value.

    Common mistakes

    • n bits store 2**n different values, from 0 up to 2**n - 1.
    • Lossy compression throws away detail and cannot be undone; lossless can be reversed exactly.
    Tiếng Việt

    Nén làm dữ liệu nhỏ hơn. Nén không mất mát giữ lại mọi bit, nên bạn tái tạo lại bản gốc hoàn toàn chính xác. Nén có mất mát loại bỏ chi tiết — nhỏ hơn nhưng không chính xác — và dùng cho ảnh và âm nhạc.

    Mã hóa run-length là phương pháp nén không mất mát đơn giản: lưu một chuỗi (lặp lại) dưới dạng đếm cộng giá trị.

    def rle(text):
        out = ""
        i = 0
        while i < len(text):
            run = 1
            while i + run < len(text) and text[i + run] == text[i]:
                run += 1
            out += str(run) + text[i]
            i += run
        return out
    
    print(rle("AAAABBBCCD"))   # 4A3B2C1D
    

    Lỗi thường gặp

    • n bits lưu trữ 2**n giá trị khác nhau, từ 0 đến 2**n - 1.
    • Nén có mất mát loại bỏ chi tiết và không thể đảo ngược; nén không mất mát có thể đảo ngược hoàn toàn chính xác.
  • 16 Computing concepts · ⁨Khái niệm máy tính⁩
    16.1

    Computing là gì & Chu kỳ thiết kế

    English

    Computing 计算 means solving problems with computers: input, process, output. Good software is built in a design cycle 设计循环 — plan, write, test, improve — repeated many times.

    • Break a problem down, build a small part, test it, then add more.
    • Programmers work in teams and reuse each other's code.
    Tiếng Việt

    Computing nghĩa là giải quyết vấn đề bằng máy tính: đầu vào, xử lý, đầu ra. Phần mềm tốt được xây dựng theo chu kỳ thiết kế — lên kế hoạch, viết, kiểm thử, cải tiến — lặp lại nhiều lần.

    • Chia nhỏ vấn đề, xây dựng một phần nhỏ, kiểm thử nó, sau đó thêm phần khác.
    • Lập trình viên làm việc theo nhóm và tái sử dụng code của nhau.
    16.2

    Internet

    English

    The Internet 互联网 is a network 网络 of networks. Data is split into packets 数据包 that travel separately and are put back together at the other end. Shared rules called protocols 协议 (such as TCP/IP) make this work. If one path breaks, packets take another route — this is redundancy 冗余, which gives fault tolerance 容错.

    Layer Job
    HTTP request and send web pages
    TCP reliable delivery, in order
    IP addressing and routing
    Tiếng Việt

    Internet là mạng của các mạng. Dữ liệu được chia thành các gói tin di chuyển riêng biệt và được ghép lại ở đầu kia. Các quy tắc chung gọi là giao thức (như TCP/IP) làm cho điều này hoạt động. Nếu một đường truyền bị hỏng, gói tin đi đường khác — đây là sự dư thừa, mang lại khả năng chịu lỗi.

    Bản đồ Internet: mỗi đường là một đường đi giữa hai mạng
    Bản đồ Internet: mỗi đường là một đường đi giữa hai mạng
    Lớp Nhiệm vụ
    HTTP yêu cầu và gửi trang web
    TCP giao đáng tin cậy, theo thứ tự
    IP địa chỉ và định tuyến
    16.3

    Tính toán song song & phân tán

    English

    Sequential 顺序 code does one step at a time. Parallel 并行 computing does several steps at once on many cores 核心, which can give a speedup 加速. Distributed 分布式 computing spreads the work across many computers, such as a cloud.

    • Not everything can run in parallel: some steps must wait for an earlier result.
    Tiếng Việt

    Code tuần tự thực hiện từng bước một. Tính toán song song thực hiện nhiều bước cùng lúc trên nhiều nhân, có thể tăng tốc độ. Tính toán phân tán chia sẻ công việc across nhiều máy tính, ví dụ như đám mây.

    • Không phải mọi thứ đều chạy song song: một số bước phải chờ kết quả từ bước trước đó.
    16.4

    Tác động của tính toán

    English

    Computing brings both benefits and harms. The digital divide 数字鸿沟 means not everyone has equal access to it. Software can carry bias 偏见 from the data it learns from. Respect intellectual property 知识产权 (licences), and protect people's personal data 个人数据 and privacy 隐私.

    Common mistakes

    • The Internet and the World Wide Web are not the same: the Web is one service that runs on top of the Internet.
    • More processor cores help only if the work can be split into parts that run at the same time.
    Tiếng Việt

    Tính toán mang lại cả lợi ích và tác hại. Khoảng cách số nghĩa là không ai cũng có quyền truy cập bình đẳng vào nó. Phần mềm có thể chứa thiên kiến từ dữ liệu mà nó học hỏi. Tôn trọng sở hữu trí tuệ (bản quyền), và bảo vệ dữ liệu cá nhân cũng như quyền riêng tư của con người.

    Lỗi thường gặp

    • Internet và World Wide Web không phải là cùng một thứ: Web là một dịch vụ chạy trên nền tảng của Internet.
    • Nhiều nhân xử lý hơn chỉ giúp ích nếu công việc có thể chia nhỏ thành các phần chạy cùng lúc.
  • 17 Putting it together · ⁨Kết hợp tất cả lại⁩
    17.1

    Các mini-project cuối khóa

    English

    A mini-project 小项目 combines earlier ideas: data in a list, a function with selection inside a loop, and printed output. This is also the shape of the AP Create Performance Task.

    Project: average mark

    Project: count passes

    Project: filter to a new list

    The AP Create Task wants a list, a parameterised procedure 过程 that uses selection 选择 and iteration 迭代, and some input/output. Each project above is exactly that shape — build small pieces, then join them.

    Common mistakes

    • Build in small steps and test each part before moving on — do not write it all at once.
    • Read the whole task first, then plan the input → process → output before you code.
    Tiếng Việt

    Một mini-project kết hợp các ý tưởng đã học: dữ liệu trong danh sách, hàm có chọn lọc bên trong vòng lặp, và đầu ra được in ra. Đây cũng chính là cấu trúc của AP Create Performance Task.

    Project: điểm trung bình

    def average(marks):
        if len(marks) == 0:
            return 0
        return round(sum(marks) / len(marks), 1)
    
    print(average([88, 71, 95, 60]))   # 78.5
    

    Project: đếm số lượng đạt

    def count_passes(marks, pass_mark=60):
        passes = 0
        for m in marks:                 # iteration
            if m >= pass_mark:          # selection
                passes += 1
        return passes
    
    print(count_passes([88, 50, 95, 60]))   # 3
    

    Project: lọc sang danh sách mới

    def merit(marks):
        return [m for m in marks if m >= 80]
    
    print(merit([88, 71, 95, 60]))     # [88, 95]
    

    AP Create Task yêu cầu một danh sách, một thủ tục tham số hóa sử dụng chọn lọc và lặp, cùng với một số đầu vào/đầu ra. Mỗi project ở trên đều đúng cấu trúc đó — hãy xây dựng từng phần nhỏ, sau đó ghép chúng lại.

    Lỗi thường gặp

    • Xây dựng theo từng bước nhỏ và kiểm thử từng phần trước khi chuyển sang phần tiếp theo — đừng viết tất cả cùng một lúc.
    • Đọc hết bài tập trước, sau đó lập kế hoạch đầu vào → xử lý → đầu ra trước khi code.
    Mini-project: dữ liệu → hàm → kết quả in
    Mini-project: dữ liệu → hàm → kết quả in

Log in or create account · ⁨Đăng nhập hoặc tạo tài khoản⁩

IGCSE, A-Level & AP