Skip to Content
Python🤔 What the Python! Lạ thế nhỉ?{} là dict, không phải set!

{} là dict, không phải set!

Hiện tượng lạ

# Tạo set với các phần tử my_set = {1, 2, 3} print(type(my_set)) # <class 'set'> # Vậy tạo set rỗng cũng dùng {}? empty = {} print(type(empty)) # <class 'dict'> <- What the Python?!

Tại sao {1, 2, 3} là set nhưng {} lại là dict?! 🤔

Giải thích

Dictionary có trước, Set có sau

Python được tạo ra năm 1991, Dictionary (dict) đã có từ đầu và sử dụng cú pháp {}.

Set (set) chỉ được thêm vào Python 2.4 (năm 2004), 13 năm sau!

# Dictionary - Có từ Python 1.0 (1991) my_dict = {"key": "value"} # Set - Thêm vào Python 2.4 (2004) my_set = {1, 2, 3}

{} đã được “chiếm chỗ” bởi dict

Khi set được thêm vào, {} đã được dùng cho dict rỗng. Để tránh breaking changes (phá vỡ code cũ), Python giữ nguyên {} = dict rỗng.

Cách tạo set và dict rỗng

Dictionary rỗng

# Cách 1: Dùng {} empty_dict = {} print(type(empty_dict)) # <class 'dict'> # Cách 2: Dùng dict() empty_dict = dict() print(type(empty_dict)) # <class 'dict'> # Cả 2 cách đều OK

Set rỗng

# KHÔNG THỂ dùng {} empty_set = {} # ❌ Đây là dict, không phải set! # PHẢI dùng set() empty_set = set() print(type(empty_set)) # <class 'set'> ✅ # Đây là CÁCH DUY NHẤT để tạo set rỗng

So sánh Set và Dict

Cú pháp với elements

# Set - chỉ có values my_set = {1, 2, 3} print(my_set) # {1, 2, 3} # Dict - có key:value pairs my_dict = {"a": 1, "b": 2, "c": 3} print(my_dict) # {'a': 1, 'b': 2, 'c': 3} # Python phân biệt bằng dấu : # - Không có : → Set # - Có : → Dict

Cú pháp rỗng

# Set rỗng - PHẢI dùng constructor empty_set = set() # Dict rỗng - Dùng {} hoặc constructor empty_dict = {} empty_dict = dict() # Cũng OK

Các trường hợp dễ nhầm

1. Khởi tạo set rỗng

# SAI - Vô tình tạo dict def process_unique_items(): seen = {} # ❌ Đây là dict! seen.add(1) # AttributeError: 'dict' object has no attribute 'add' # ĐÚNG def process_unique_items(): seen = set() # ✅ seen.add(1) # OK!

2. Default value trong function

# SAI - Default là dict, không phải set def track_ids(new_ids, existing={}): # ❌ {} là dict existing.add(new_ids) # Lỗi! # ĐÚNG def track_ids(new_ids, existing=None): if existing is None: existing = set() # ✅ existing.add(new_ids)

3. Type annotation

from typing import Set, Dict # Nếu dùng type hints, dễ phát hiện lỗi def get_unique_items() -> Set[int]: return {} # ❌ Type checker sẽ báo lỗi: Expected Set, got Dict # ĐÚNG def get_unique_items() -> Set[int]: return set() # ✅

Tại sao cần set rỗng?

Use case 1: Tracking unique items

def find_unique_chars(text): unique = set() # Bắt đầu với set rỗng for char in text: unique.add(char) return unique print(find_unique_chars("hello")) # {'h', 'e', 'l', 'o'}

Use case 2: Filtering duplicates

def remove_duplicates(items): seen = set() # Set rỗng để track result = [] for item in items: if item not in seen: seen.add(item) result.append(item) return result print(remove_duplicates([1, 2, 2, 3, 1, 4])) # [1, 2, 3, 4]

Use case 3: Set operations từ rỗng

# Bắt đầu với set rỗng, sau đó union all_tags = set() for article in articles: all_tags = all_tags.union(article.tags) # Hoặc all_tags = set() for article in articles: all_tags |= set(article.tags) # Union assignment

Cách debug và phát hiện

1. Kiểm tra type

mystery = {} # Debug print(f"Type: {type(mystery)}") # <class 'dict'> print(f"Is dict: {isinstance(mystery, dict)}") # True print(f"Is set: {isinstance(mystery, set)}") # False

2. Lỗi khi dùng set methods

data = {} # Nếu vô tình tạo dict thay vì set data.add(1) # AttributeError: 'dict' object has no attribute 'add' # → Lỗi này cho biết data là dict, không phải set!

3. Dùng IDE/Linter

# PyCharm, VS Code với Pylint sẽ cảnh báo unique_items: Set[int] = {} # Warning: Expected Set, got dict

So sánh đầy đủ

Mục đíchCú phápTypeVí dụ
Set rỗngset()sets = set()
Set có phần tử{1, 2, 3}sets = {1, 2, 3}
Dict rỗng{} hoặc dict()dictd = {}
Dict có phần tử{"a": 1}dictd = {"a": 1}

Set comprehension vs Dict comprehension

# Set comprehension - Không có : squares_set = {x**2 for x in range(5)} print(squares_set) # {0, 1, 4, 9, 16} print(type(squares_set)) # <class 'set'> # Dict comprehension - Có : squares_dict = {x: x**2 for x in range(5)} print(squares_dict) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} print(type(squares_dict)) # <class 'dict'> # Comprehension rỗng? # - Set: {x for x in []} → set() (rỗng) # - Dict: {x: x for x in []} → {} (rỗng)

Bảng tổng hợp methods

Set methods (không có trong dict)

s = set() s.add(1) # ✅ Set có s.remove(1) # ✅ Set có s.discard(1) # ✅ Set có s.union({2, 3}) # ✅ Set có

Dict methods (không có trong set)

d = {} d["key"] = "value" # ✅ Dict có d.get("key") # ✅ Dict có d.keys() # ✅ Dict có d.values() # ✅ Dict có d.items() # ✅ Dict có

Best Practices

✅ Nên làm

# 1. Luôn dùng set() cho set rỗng unique_items = set() # ✅ Rõ ràng # 2. Dùng type hints from typing import Set def get_tags() -> Set[str]: return set() # ✅ # 3. Kiểm tra type khi debug if not isinstance(data, set): raise TypeError(f"Expected set, got {type(data)}")

❌ Tránh làm

# 1. Dùng {} cho set rỗng unique_items = {} # ❌ Nhầm lẫn! # 2. Không kiểm tra type def process(data): data.add(1) # ❌ Nếu data là dict sẽ lỗi # 3. Mixed types không rõ ràng def create_collection(is_unique): return set() if is_unique else {} # ❌ Confusing

Lịch sử Python - Tại sao như vậy?

Timeline

  • 1991: Python ra đời, dict dùng {}
  • 2004: Python 2.4 - Set được thêm vào
  • Vấn đề: {} đã được dùng cho dict rỗng
  • Giải pháp:
    • Giữ {} = dict rỗng (backward compatibility)
    • Dùng set() cho set rỗng
    • Dùng {1, 2, 3} cho set có phần tử (phân biệt bằng không có :)

Lý do không thay đổi

# Nếu thay đổi {} thành set: # - Hàng triệu dòng code cũ sẽ bị hỏng # - Dict rỗng phải dùng dict() (không tiện) # - Breaking change quá lớn

Tóm tắt

Cú phápKiểuGhi chú
{}dictDict rỗng
{1, 2, 3}setSet với phần tử
{"a": 1}dictDict với key:value
set()setSet rỗng (cách duy nhất)
dict()dictDict rỗng (giống {})

Ghi nhớ

{} là dict, không phải set!

  • ✅ Set rỗng: set() (cách DUY NHẤT)
  • ✅ Dict rỗng: {} hoặc dict()
  • 🔍 Python phân biệt set/dict bằng dấu :
    • Không có : → Set: {1, 2, 3}
    • : → Dict: {"a": 1, "b": 2}

Tip: Nhớ rằng dictionary “có trước” nên “chiếm” được {}!

Last updated on