Mục lục
Mục tiêu bài học
Sau bài này, bạn sẽ:
- Phân biệt được
/(true division) và//(floor division) trong Python 3.x. - Biết thứ tự ưu tiên (operator precedence) của các nhóm toán tử và khi nào nên dùng dấu ngoặc.
- Viết được biểu thức so sánh nối chuỗi như
0 < x < 10. - Hiểu cơ chế short-circuit của
and/or. - Dùng đúng
is Nonethay vì== None. - Kiểm tra phần tử bằng
in/not in.
Toán tử số học
Python 3.x có 7 toán tử số học cơ bản:
| Toán tử | Tên gọi | Ví dụ | Kết quả |
|---|---|---|---|
+ | Cộng | 7 + 2 | 9 |
- | Trừ | 7 - 2 | 5 |
* | Nhân | 7 * 2 | 14 |
/ | True division | 7 / 2 | 3.5 (float) |
// | Floor division | 7 // 2 | 3 (int) |
% | Modulo (lấy dư) | 7 % 2 | 1 |
** | Lũy thừa | 7 ** 2 | 49 |
Phân biệt / và //
Đây là khác biệt quan trọng giữa Python 2 và Python 3. Trong Python 3.x, / luôn trả về float, kể cả khi cả hai toán hạng đều là int:
# True division: luôn trả về float
print(10 / 4) # 2.5
print(8 / 2) # 4.0 (không phải 4!)
print(type(8 / 2)) # <class 'float'>
# Floor division: làm tròn xuống số nguyên gần nhất
print(10 // 4) # 2
print(8 // 2) # 4
print(type(8 // 2)) # <class 'int'>
Lưu ý floor division // làm tròn về phía âm vô cùng, không phải về 0:
print(-7 // 2) # -4 (không phải -3)
print(-7 / 2) # -3.5
Modulo và lũy thừa
# Modulo: lấy phần dư của phép chia nguyên
print(17 % 5) # 2 (17 = 3*5 + 2)
print(10 % 2) # 0 → 10 là số chẵn
# Lũy thừa: a ** b = a^b
print(2 ** 10) # 1024
print(2 ** 0.5) # 1.4142135623730951 (căn bậc 2 của 2)
Toán tử % hay được dùng để kiểm tra chẵn lẻ hoặc chia batch dữ liệu sau này. ** hay xuất hiện trong công thức xác suất, neural network (ví dụ x ** 2 trong MSE loss).
Operator precedence và dấu ngoặc
Khi một biểu thức có nhiều toán tử, Python tính theo thứ tự ưu tiên (precedence). Bảng dưới liệt kê các nhóm hay gặp, từ ưu tiên cao đến thấp:
| Hạng | Toán tử | Mô tả |
|---|---|---|
| 1 | (...) | Dấu ngoặc — ưu tiên cao nhất |
| 2 | ** | Lũy thừa (kết hợp phải sang trái) |
| 3 | +x, -x | Unary plus / minus |
| 4 | *, /, //, % | Nhân, chia, chia nguyên, modulo |
| 5 | +, - | Cộng, trừ |
| 6 | ==, !=, <, >, <=, >=, is, in | So sánh, identity, membership |
| 7 | not | Phủ định logic |
| 8 | and | Và logic |
| 9 | or | Hoặc logic |
Ví dụ:
# Nhân được tính trước cộng
print(2 + 3 * 4) # 14, không phải 20
# Dùng dấu ngoặc để đổi thứ tự
print((2 + 3) * 4) # 20
# Lũy thừa kết hợp phải sang trái
print(2 ** 3 ** 2) # 512 (= 2 ** (3 ** 2) = 2 ** 9)
print((2 ** 3) ** 2) # 64 (= 8 ** 2)
Quy tắc thực dụng: khi không chắc, đặt dấu ngoặc. Code đọc rõ ràng quan trọng hơn việc tiết kiệm 2 ký tự.
Bảng đầy đủ về precedence ở mục Operator precedence trong Python Language Reference (xem phần sources).
Toán tử so sánh và chained comparison
Toán tử so sánh trả về kiểu bool (True hoặc False):
| Toán tử | Ý nghĩa | Ví dụ |
|---|---|---|
== | Bằng giá trị | 3 == 3 → True |
!= | Khác giá trị | 3 != 4 → True |
< | Nhỏ hơn | 3 < 4 → True |
> | Lớn hơn | 3 > 4 → False |
<= | Nhỏ hơn hoặc bằng | 3 <= 3 → True |
>= | Lớn hơn hoặc bằng | 3 >= 4 → False |
x = 5
print(x == 5) # True
print(x != 10) # True
print(x >= 5) # True
# So sánh cũng dùng được với string (theo thứ tự lexicographic)
print("apple" < "banana") # True
Chained comparison
Python cho phép nối nhiều phép so sánh trong một biểu thức, ngắn gọn và đọc gần như toán học:
x = 7
# Kiểm tra x nằm trong khoảng (0, 10)
print(0 < x < 10) # True
# Tương đương với:
print(0 < x and x < 10) # True
# Có thể nối nhiều hơn
score = 75
print(0 <= score <= 100) # True
Lưu ý: chained comparison đánh giá biến ở giữa chỉ một lần. Đây là ưu điểm so với viết 0 < f(x) and f(x) < 10 (gọi f hai lần).
Toán tử logic và short-circuit
Python có 3 toán tử logic dạng từ khóa: and, or, not.
| Biểu thức | Kết quả |
|---|---|
True and True | True |
True and False | False |
True or False | True |
False or False | False |
not True | False |
not False | True |
age = 25
has_id = True
# Kết hợp điều kiện
print(age >= 18 and has_id) # True
print(age < 18 or has_id) # True
print(not has_id) # False
Short-circuit evaluation
Cả and và or đánh giá lười (lazy): chỉ tính toán hạng bên phải khi cần.
A and B: nếuAlà falsy, trả về luônA, không đánh giáB.A or B: nếuAlà truthy, trả về luônA, không đánh giáB.
# Tránh chia cho 0 nhờ short-circuit
x = 0
if x != 0 and 10 / x > 1:
print("ok")
# Không lỗi vì vế phải không được đánh giá khi x == 0
# Đặt giá trị mặc định bằng or
name = ""
display = name or "Anonymous"
print(display) # Anonymous
Lưu ý nhỏ: and / or trả về một trong hai toán hạng (không phải lúc nào cũng là True / False):
print(0 or "hello") # "hello"
print(1 and "hello") # "hello"
print(0 and "hello") # 0
Toán tử gán mở rộng
Toán tử gán mở rộng (augmented assignment) là cách viết ngắn cho biểu thức kiểu x = x <op> y:
| Viết tắt | Tương đương |
|---|---|
x += 3 | x = x + 3 |
x -= 3 | x = x - 3 |
x *= 3 | x = x * 3 |
x /= 3 | x = x / 3 |
x //= 3 | x = x // 3 |
x %= 3 | x = x % 3 |
x **= 3 | x = x ** 3 |
total = 0
total += 10 # total = 10
total += 5 # total = 15
total *= 2 # total = 30
total //= 4 # total = 7
print(total) # 7
Augmented assignment hay xuất hiện khi cộng dồn loss, đếm số sample, hoặc cập nhật trọng số trong training loop.
Python không có ++ hay -- như C / JavaScript. Muốn tăng 1, dùng x += 1.
Identity: is / is not vs ==
Có hai khái niệm dễ nhầm:
==so sánh giá trị (equality).isso sánh identity — hai biến có cùng tham chiếu đến một object trong bộ nhớ hay không (tương đươngid(a) == id(b)).
a = [1, 2, 3]
b = [1, 2, 3]
c = a
print(a == b) # True (cùng giá trị)
print(a is b) # False (hai object khác nhau)
print(a is c) # True (cùng object)
Khi nào dùng is?
Theo PEP 8, dùng is / is not khi so sánh với các singleton (object duy nhất) như None, True, False:
value = None
# Đúng chuẩn PEP 8
if value is None:
print("không có giá trị")
if value is not None:
print("có giá trị")
# Tránh viết: if value == None
# Lý do: == có thể bị class tự định nghĩa __eq__ ghi đè,
# trong khi None luôn là singleton duy nhất.
Cảnh báo: is với int nhỏ hoặc string ngắn đôi khi trả về True do CPython caching (ví dụ a = 256; b = 256; a is b). Đừng dựa vào hành vi này — luôn dùng == để so sánh giá trị.
Membership: in / not in
in kiểm tra một phần tử có thuộc một tập hợp (sequence / container) hay không, trả về bool. not in là phủ định.
# Với string: kiểm tra substring
print("py" in "python") # True
print("java" not in "python") # True
# Với list
fruits = ["apple", "banana", "cherry"]
print("apple" in fruits) # True
print("mango" not in fruits) # True
# Với dict: chỉ kiểm tra trên KEYS, không phải values
ages = {"An": 25, "Bình": 30}
print("An" in ages) # True
print(25 in ages) # False (25 là value, không phải key)
Đây mới là cái nhìn xem trước (preview). Chi tiết về list, tuple, dict, set sẽ học từ Bài 11 trở đi. Hiện tại chỉ cần nhớ: in trả về bool và dùng được với mọi container.
Bài tập thực hành
Mở Google Colab (đã làm quen ở Bài 3) và thử các bài sau. Mục tiêu là tự gõ tay, đoán kết quả trước khi chạy, rồi đối chiếu.
Bài 1: Phân biệt / và //
Cho hai số a = 23, b = 4. Viết code in ra:
- Thương đầy đủ (
a / b) - Phần nguyên của thương (
a // b) - Phần dư (
a % b) - Kiểm tra đẳng thức:
a == (a // b) * b + (a % b)phải trả vềTrue.
Bài 2: Kiểm tra điểm hợp lệ
Cho biến score nhận từ input(). Dùng chained comparison để in ra True nếu 0 <= score <= 10, ngược lại in False. Gợi ý: nhớ convert input() sang float.
Bài 3: Năm nhuận
Một năm được coi là nhuận nếu: chia hết cho 4 và (không chia hết cho 100 hoặc chia hết cho 400). Viết biểu thức bool tính giá trị is_leap cho biến year bất kỳ, sử dụng %, and, or, not. Test với 2000 (True), 1900 (False), 2024 (True), 2023 (False).
Tổng kết
- Số học:
+ - * / // % **. Nhớ/trả về float,//trả về int trong Python 3.x. - Precedence: lũy thừa > nhân chia > cộng trừ > so sánh >
not>and>or. Dùng dấu ngoặc khi nghi ngờ. - So sánh trả về
bool; có thể nối chuỗi như0 < x < 10. - Logic
and/orcó short-circuit — hữu ích để tránh lỗi runtime và đặt giá trị mặc định. - Gán mở rộng
+= -= *= /= //= %= **=rút gọn cập nhật biến. - Dùng
is/is notvớiNone/True/False; còn lại dùng==. in/not inkiểm tra membership cho string, list, dict (theo key) và mọi container.
Bài tiếp theo sẽ dùng các biểu thức bool xây dựng được ở đây để rẽ nhánh chương trình bằng if / elif / else.
Tài liệu tham khảo
- Python Language Reference - Operator Precedence
- Python Docs - Numeric Types (Arithmetic Operations)
- Python Language Reference - Comparisons (Chained Comparisons)
- Python Language Reference - Boolean Operations (Short-circuit)
- Python Language Reference - Membership Test Operations
- Python Language Reference - Identity Comparisons (is / is not)
- PEP 8 - Programming Recommendations (so sánh với None)
- Python Docs - Augmented Assignment Statements
