True + True = 2 - Boolean là int?!
Hiện tượng lạ
Phần tiêu đề “Hiện tượng lạ”# Phép toán với Booleanprint(True + True) # 2print(True + False) # 1print(True * 5) # 5print(False * 100) # 0
# So sánhprint(True == 1) # Trueprint(False == 0) # True
# isinstanceprint(isinstance(True, int)) # Trueprint(isinstance(False, int)) # TrueWhat the Python?! Boolean có thể cộng, nhân như số? Và isinstance(True, int) trả về True?! 😱
Giải thích
Phần tiêu đề “Giải thích”Boolean là subclass của int
Phần tiêu đề “Boolean là subclass của int”Trong Python, bool là subclass của int!
# Kiểm tra class hierarchyprint(bool.__bases__) # (<class 'int'>,)print(issubclass(bool, int)) # True
# Bool inherits từ intprint(type(True)) # <class 'bool'>print(type(False)) # <class 'bool'>
# Nhưng cũng là intprint(isinstance(True, int)) # Trueprint(isinstance(False, int)) # TrueGiá trị của True và False
Phần tiêu đề “Giá trị của True và False”# True = 1, False = 0print(int(True)) # 1print(int(False)) # 0
# Chúng BẰNG 1 và 0print(True == 1) # Trueprint(False == 0) # True
# Nhưng không phải cùng object (identity khác)print(True is 1) # Falseprint(False is 0) # FalseArithmetic với Boolean
Phần tiêu đề “Arithmetic với Boolean”Phép cộng
Phần tiêu đề “Phép cộng”print(True + True) # 2print(True + False) # 1print(False + False) # 0
# Cộng với sốprint(True + 5) # 6print(False + 10) # 10print(3 + True) # 4Phép nhân
Phần tiêu đề “Phép nhân”print(True * 5) # 5print(False * 100) # 0print(True * False) # 0print(True * True) # 1Phép trừ và chia
Phần tiêu đề “Phép trừ và chia”print(True - False) # 1print(5 - True) # 4print(10 / True) # 10.0print(10 // True) # 10Phép mũ
Phần tiêu đề “Phép mũ”print(True ** 10) # 1print(2 ** True) # 2print(2 ** False) # 1Use cases hợp lệ
Phần tiêu đề “Use cases hợp lệ”1. Đếm số lượng True
Phần tiêu đề “1. Đếm số lượng True”# Đếm số phần tử thỏa điều kiệnnumbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]count_even = sum(n % 2 == 0 for n in numbers)print(count_even) # 5
# sum() hoạt động vì True = 1, False = 02. Boolean indexing
Phần tiêu đề “2. Boolean indexing”options = ["No", "Yes"]is_confirmed = True
# Dùng boolean làm indexprint(options[is_confirmed]) # "Yes"print(options[False]) # "No"
# Tương đươngprint(options[1]) # "Yes"print(options[0]) # "No"3. Conditional arithmetic
Phần tiêu đề “3. Conditional arithmetic”def calculate_price(base_price, is_member): # Discount 10% cho member discount = is_member * 0.1 # True * 0.1 = 0.1, False * 0.1 = 0 return base_price * (1 - discount)
print(calculate_price(100, True)) # 90.0print(calculate_price(100, False)) # 100.04. Toggle values
Phần tiêu đề “4. Toggle values”# Chuyển đổi 0 <-> 1value = 0value = 1 - value # Toggleprint(value) # 1
# Tương tự với booleanflag = Falseflag = not flag # Cách thông thường# hoặcflag = True - flag # Trick (không khuyến khích)Lịch sử - Tại sao thiết kế như vậy?
Phần tiêu đề “Lịch sử - Tại sao thiết kế như vậy?”Python 2.2 (2001)
Phần tiêu đề “Python 2.2 (2001)”- Trước Python 2.3, không có kiểu
boolriêng - Dùng
1và0thay cho True và False
# Python 2.2 trở về trướcif 1: # Dùng 1 thay cho True print("True")Python 2.3 (2003)
Phần tiêu đề “Python 2.3 (2003)”- Thêm
booltype vớiTruevàFalse - Quyết định thiết kế: Làm
boolsubclass củaintđể:- ✅ Backward compatibility
- ✅ Code cũ vẫn chạy
- ✅
1và0vẫn có thể dùng như boolean
Khi nào nên/không nên dùng arithmetic
Phần tiêu đề “Khi nào nên/không nên dùng arithmetic”✅ Nên dùng
Phần tiêu đề “✅ Nên dùng”# 1. Đếm số lượngcount = sum(condition for item in items)
# 2. Boolean indexing (nếu rõ ràng)result = ["Fail", "Pass"][is_passed]
# 3. Bitwise operationsflags = is_read | (is_write << 1) | (is_execute << 2)❌ Không nên dùng
Phần tiêu đề “❌ Không nên dùng”# 1. Phép toán khó hiểudiscount = is_member * 0.1 # ❌ Confusing# Tốt hơn:discount = 0.1 if is_member else 0 # ✅ Clear
# 2. Boolean arithmetic phức tạpresult = (flag1 + flag2) * flag3 - flag4 # ❌ What?# Tốt hơn:if flag1 or flag2: if flag3 and not flag4: result = ... # ✅ Readable
# 3. Toggle với arithmeticvalue = 1 - value # ❌ Cryptic# Tốt hơn:value = not value # ✅ ClearSo sánh với 1 và 0
Phần tiêu đề “So sánh với 1 và 0”Equality (==)
Phần tiêu đề “Equality (==)”# True == 1print(True == 1) # Trueprint(False == 0) # True
# Nhưng cẩn thận!print(2 == True) # False (2 != 1)print(-1 == True) # Falseprint(0.0 == False) # Trueprint(1.0 == True) # TrueIdentity (is)
Phần tiêu đề “Identity (is)”# True is not 1print(True is 1) # Falseprint(False is 0) # False
# True và False là singletona = Trueb = Trueprint(a is b) # True (cùng object)Hash values
Phần tiêu đề “Hash values”# True và 1 có cùng hashprint(hash(True)) # 1print(hash(1)) # 1print(hash(False)) # 0print(hash(0)) # 0
# Vì vậy có thể gây vấn đề trong dict/setd = {True: "boolean", 1: "integer"}print(d) # {True: 'integer'} - 1 overwrite True!Trường hợp đặc biệt
Phần tiêu đề “Trường hợp đặc biệt”Dictionary keys
Phần tiêu đề “Dictionary keys”# True và 1 coi như cùng key!d = {}d[True] = "A"d[1] = "B"print(d) # {True: 'B'} - Chỉ có 1 entry!
# Tương tự với False và 0d = {}d[False] = "A"d[0] = "B"print(d) # {False: 'B'}Set membership
Phần tiêu đề “Set membership”# True và 1 coi như duplicates = {True, 1, 2, False, 0, 3}print(s) # {False, True, 2, 3}# Chỉ giữ True và False, loại 1 và 0List/Tuple indexing
Phần tiêu đề “List/Tuple indexing”lst = ["A", "B", "C"]
# Boolean làm indexprint(lst[True]) # "B" (index 1)print(lst[False]) # "A" (index 0)
# Nhưng cẩn thận - chỉ dùng được với index 0, 1# lst[True + True] sẽ là lst[2]Truthy vs True
Phần tiêu đề “Truthy vs True”Phân biệt truthy và True
Phần tiêu đề “Phân biệt truthy và True”# Truthy values (evaluate to True)truthy_values = [1, "hello", [1], {1: 1}, True]
for val in truthy_values: if val: # Truthy check print(f"{val} is truthy")
# Nhưng không phải tất cả đều == Trueprint(1 == True) # Trueprint("hello" == True) # Falseprint([1] == True) # False
# Chỉ 1 và True == TrueBool() conversion
Phần tiêu đề “Bool() conversion”# Conversion to boolprint(bool(0)) # Falseprint(bool(1)) # Trueprint(bool(2)) # True (truthy, not True)print(bool("")) # Falseprint(bool("hi")) # Trueprint(bool([])) # Falseprint(bool([1])) # TrueBest Practices
Phần tiêu đề “Best Practices”✅ Nên làm
Phần tiêu đề “✅ Nên làm”# 1. Dùng True/False thay vì 1/0 cho booleanis_valid = True # ✅is_valid = 1 # ❌
# 2. Dùng boolean operationsif is_active and not is_deleted: # ✅ pass
# 3. Explicit conversioncount = sum(1 for x in items if condition(x)) # ✅
# 4. Dùng bool() để convertis_empty = bool(my_list) # ✅ Clear intent❌ Tránh làm
Phần tiêu đề “❌ Tránh làm”# 1. Arithmetic với booleanresult = flag1 + flag2 # ❌ Confusingresult = flag1 or flag2 # ✅ Clear
# 2. So sánh explicit với True/Falseif flag == True: # ❌ Redundantif flag: # ✅ Pythonic
# 3. Boolean arithmetic tricksvalue = (not value) * 1 # ❌ Crypticvalue = int(not value) # ✅ If needed
# 4. Dùng 1/0 thay True/Falsereturn 1 if condition else 0 # ❌return True if condition else False # ✅# Hoặc tốt hơn:return condition # ✅Type checking
Phần tiêu đề “Type checking”# Kiểm tra typedef process(value): # Kiểm tra chính xác là bool if type(value) is bool: print("It's a bool") elif isinstance(value, bool): print("It's a bool or subclass") elif isinstance(value, int): print("It's an int (includes bool!)")
process(True) # "It's a bool"process(1) # "It's an int (includes bool!)"
# Cẩn thận với isinstanceisinstance(True, int) # True - bool is int!Tóm tắt
Phần tiêu đề “Tóm tắt”| Expression | Result | Reason |
|---|---|---|
True + True |
2 |
1 + 1 |
True * 5 |
5 |
1 * 5 |
False + 10 |
10 |
0 + 10 |
True == 1 |
True |
Cùng giá trị |
True is 1 |
False |
Khác object |
isinstance(True, int) |
True |
bool subclass của int |
type(True) is int |
False |
type là bool |
hash(True) |
1 |
Same hash |
{True: 'a', 1: 'b'} |
{True: 'b'} |
1 overwrites True |
Ghi nhớ
Phần tiêu đề “Ghi nhớ”
boollà subclass củainttrong Python!
- ✅
True == 1vàFalse == 0- ✅ Có thể dùng arithmetic:
True + True = 2- ✅ Hữu ích cho
sum()counting- ⚠️
True is not 1(khác object)- ⚠️ Trong dict/set,
Truevà1là duplicate- 🎯 Luôn dùng
True/Falsethay vì1/0cho boolean logic
Best practice: Dùng boolean cho logic, dùng int cho arithmetic. Không mix!