Bài 7: Dictionaries - Từ Điển (Phần 1)
Mục Tiêu Bài Học
Sau khi hoàn thành bài này, bạn sẽ:
- ✅ Hiểu dictionary là gì và key-value pairs
- ✅ Tạo và truy cập dictionary
- ✅ Thêm, xóa, sửa phần tử trong dict
- ✅ Sử dụng dictionary methods cơ bản
- ✅ Iterate through dictionaries
Dictionary Là Gì?
Dictionary (dict) là collection lưu trữ dữ liệu dạng key-value pairs (cặp khóa-giá trị). Dictionary là unordered (Python 3.7+ giữ insertion order), mutable, và không cho phép key trùng.
# Dictionary với dấu ngoặc nhọn {}person = { "name": "Alice", "age": 25, "email": "[email protected]"} print(type(person)) # <class 'dict'>
Key-Value Pairs:
# Syntax: {key: value, key: value, ...}student = { "id": 101, # key: "id", value: 101 "name": "Bob", # key: "name", value: "Bob" "grade": 85, # key: "grade", value: 85 "passed": True # key: "passed", value: True} # Key phải là immutable (string, number, tuple)# Value có thể là bất kỳ kiểu gì
So sánh với List:
# List - truy cập bằng index (số)fruits = ["apple", "banana", "orange"]print(fruits[0]) # apple # Dictionary - truy cập bằng key (string, number, ...)fruit_prices = { "apple": 2.5, "banana": 1.5, "orange": 3.0}print(fruit_prices["apple"]) # 2.5
Tạo Dictionary
Cách 1: Dùng Dấu Ngoặc Nhọn {}
# Empty dictionaryempty_dict = {}print(type(empty_dict)) # <class 'dict'> # Dictionary với dataperson = { "name": "Alice", "age": 25, "city": "Hanoi"} # Mixed value typesmixed = { "string": "Hello", "number": 42, "float": 3.14, "bool": True, "list": [1, 2, 3], "dict": {"nested": "value"}} # Multi-line (readable)user = { "username": "alice123", "email": "[email protected]", "is_active": True, "roles": ["user", "admin"]}
Cách 2: dict() Constructor
# Từ keyword argumentsperson = dict(name="Bob", age=30, city="HCMC")print(person) # {'name': 'Bob', 'age': 30, 'city': 'HCMC'} # Từ list of tuplespairs = [("a", 1), ("b", 2), ("c", 3)]my_dict = dict(pairs)print(my_dict) # {'a': 1, 'b': 2, 'c': 3} # Từ 2 lists (zip)keys = ["name", "age", "city"]values = ["Charlie", 35, "Danang"]person = dict(zip(keys, values))print(person) # {'name': 'Charlie', 'age': 35, 'city': 'Danang'}
Cách 3: Dictionary Comprehension
# Tạo dict từ rangesquares = {x: x**2 for x in range(5)}print(squares) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16} # Với điều kiệnevens = {x: x**2 for x in range(10) if x % 2 == 0}print(evens) # {0: 0, 2: 4, 4: 16, 6: 36, 8: 64} # Từ listfruits = ["apple", "banana", "orange"]fruit_lengths = {f: len(f) for f in fruits}print(fruit_lengths) # {'apple': 5, 'banana': 6, 'orange': 6}
Truy Cập Phần Tử
Dùng [] (Square Brackets)
person = { "name": "Alice", "age": 25, "email": "[email protected]"} # Truy cập value bằng keyprint(person["name"]) # Aliceprint(person["age"]) # 25 # Lỗi nếu key không tồn tại# print(person["phone"]) # KeyError: 'phone'
Dùng get() Method (An toàn hơn)
person = { "name": "Alice", "age": 25} # get(key) - trả về None nếu key không tồn tạiphone = person.get("phone")print(phone) # None # get(key, default) - trả về default nếu key không tồn tạiphone = person.get("phone", "N/A")print(phone) # N/A # So sánhprint(person["name"]) # Aliceprint(person.get("name")) # Alice # print(person["phone"]) # KeyError!print(person.get("phone")) # None (không lỗi)
Nested Dictionaries
# Dictionary chứa dictionarycompany = { "name": "Tech Corp", "employees": { "alice": {"age": 25, "role": "Developer"}, "bob": {"age": 30, "role": "Manager"} }} # Truy cập nestedprint(company["name"]) # Tech Corpprint(company["employees"]["alice"]) # {'age': 25, 'role': 'Developer'}print(company["employees"]["alice"]["age"]) # 25 # An toàn với get()role = company.get("employees", {}).get("alice", {}).get("role")print(role) # Developer
Thay Đổi Dictionary
Thêm/Sửa Phần Tử
person = { "name": "Alice", "age": 25} # Thêm key mớiperson["email"] = "[email protected]"print(person)# {'name': 'Alice', 'age': 25, 'email': '[email protected]'} # Sửa value (key đã tồn tại)person["age"] = 26print(person)# {'name': 'Alice', 'age': 26, 'email': '[email protected]'} # Key không tồn tại -> thêm mới# Key đã tồn tại -> updateperson["city"] = "Hanoi" # Thêmperson["city"] = "HCMC" # Update
update() Method
person = { "name": "Alice", "age": 25} # Update từ dict khácperson.update({"email": "[email protected]", "phone": "123456"})print(person)# {'name': 'Alice', 'age': 25, 'email': '[email protected]', 'phone': '123456'} # Update với keyword argumentsperson.update(age=26, city="Hanoi")print(person) # Nếu key đã tồn tại -> update# Nếu key chưa có -> thêm mớiperson.update({"age": 27, "country": "Vietnam"})
Xóa Phần Tử
person = { "name": "Alice", "age": 25, "email": "[email protected]", "phone": "123456"} # 1. del - xóa theo keydel person["phone"]print(person) # phone đã bị xóa # Lỗi nếu key không tồn tại# del person["address"] # KeyError! # 2. pop() - xóa và trả về valueemail = person.pop("email")print(email) # [email protected]print(person) # email đã bị xóa # pop với default (không lỗi nếu key không tồn tại)phone = person.pop("phone", "N/A")print(phone) # N/A # 3. popitem() - xóa và trả về (key, value) cuối cùngitem = person.popitem()print(item) # ('age', 25)print(person) # {'name': 'Alice'} # 4. clear() - xóa tất cảperson.clear()print(person) # {}
Dictionary Methods
keys(), values(), items()
person = { "name": "Alice", "age": 25, "email": "[email protected]"} # keys() - lấy tất cả keyskeys = person.keys()print(keys) # dict_keys(['name', 'age', 'email'])print(list(keys)) # ['name', 'age', 'email'] # values() - lấy tất cả valuesvalues = person.values()print(values) # dict_values(['Alice', 25, '[email protected]'])print(list(values)) # ['Alice', 25, '[email protected]'] # items() - lấy tất cả (key, value) pairsitems = person.items()print(items)# dict_items([('name', 'Alice'), ('age', 25), ('email', '[email protected]')])print(list(items))# [('name', 'Alice'), ('age', 25), ('email', '[email protected]')]
in Operator - Check Key
person = { "name": "Alice", "age": 25} # Check key tồn tạiprint("name" in person) # Trueprint("email" in person) # Falseprint("age" not in person) # False # ⚠️ in chỉ check key, không check value!print("Alice" in person) # False (Alice là value, không phải key)print("Alice" in person.values()) # True (check trong values)
copy() - Sao Chép
original = { "name": "Alice", "age": 25} # Shallow copycopy1 = original.copy()copy1["age"] = 30print(original) # {'name': 'Alice', 'age': 25} (không đổi)print(copy1) # {'name': 'Alice', 'age': 30} # Reference (KHÔNG phải copy!)ref = originalref["age"] = 30print(original) # {'name': 'Alice', 'age': 30} (đã đổi!) # Deep copy (nested dictionaries)import copynested = { "name": "Bob", "contact": {"email": "[email protected]"}} shallow = nested.copy()shallow["contact"]["email"] = "[email protected]"print(nested["contact"]["email"]) # [email protected] (bị đổi!) deep = copy.deepcopy(nested)deep["contact"]["email"] = "[email protected]"print(nested["contact"]["email"]) # [email protected] (không đổi)
setdefault() - Lấy hoặc Set Default
person = { "name": "Alice"} # Nếu key tồn tại -> trả về valuename = person.setdefault("name", "Unknown")print(name) # Alice # Nếu key không tồn tại -> thêm với default valueage = person.setdefault("age", 0)print(age) # 0print(person) # {'name': 'Alice', 'age': 0} # So sánh với get()# get() - không thêm key mớiemail = person.get("email", "N/A")print(email) # N/Aprint(person) # {'name': 'Alice', 'age': 0} (không có email) # setdefault() - thêm key mới nếu chưa cóemail = person.setdefault("email", "[email protected]")print(email) # [email protected]print(person) # {'name': 'Alice', 'age': 0, 'email': '[email protected]'}
Iterate Through Dictionary
Loop Through Keys
person = { "name": "Alice", "age": 25, "city": "Hanoi"} # Default - loop through keysfor key in person: print(key)# name# age# city # Explicit - keys()for key in person.keys(): print(key, "->", person[key])# name -> Alice# age -> 25# city -> Hanoi
Loop Through Values
person = { "name": "Alice", "age": 25, "city": "Hanoi"} # values()for value in person.values(): print(value)# Alice# 25# Hanoi
Loop Through Items (Key-Value)
person = { "name": "Alice", "age": 25, "city": "Hanoi"} # items() - recommendedfor key, value in person.items(): print(f"{key}: {value}")# name: Alice# age: 25# city: Hanoi # Format đẹpfor key, value in person.items(): print(f"{key:<10} = {value}")# name = Alice# age = 25# city = Hanoi
Ví Dụ Thực Tế
1. Phone Book
# Danh bạ điện thoạiphonebook = { "Alice": "0123456789", "Bob": "0987654321", "Charlie": "0111222333"} # Thêm contactphonebook["Diana"] = "0444555666" # Tìm số điện thoạiname = "Alice"phone = phonebook.get(name, "Not found")print(f"{name}'s phone: {phone}") # Update sốphonebook["Bob"] = "0999888777" # Xóa contactphonebook.pop("Charlie", None) # Hiển thị toàn bộprint("\nPhone Book:")for name, phone in phonebook.items(): print(f" {name:<15} {phone}")
2. Inventory System
# Kho hànginventory = { "apple": {"quantity": 50, "price": 2.5}, "banana": {"quantity": 30, "price": 1.5}, "orange": {"quantity": 40, "price": 3.0}} # Hiển thị inventoryprint("Inventory:")for item, info in inventory.items(): qty = info["quantity"] price = info["price"] total = qty * price print(f" {item.capitalize():<10} Qty: {qty:>3} Price: ${price:>5.2f} Total: ${total:>6.2f}") # Bán hàngdef sell_item(item, quantity): if item in inventory: if inventory[item]["quantity"] >= quantity: inventory[item]["quantity"] -= quantity print(f"Sold {quantity} {item}(s)") else: print(f"Not enough {item}!") else: print(f"{item} not in inventory!") sell_item("apple", 10)sell_item("banana", 50) # Not enough # Thêm hàng mớiinventory["grape"] = {"quantity": 20, "price": 4.0}
3. Word Frequency Counter
text = """Python is an amazing programming language.Python is easy to learn and Python is powerful.""" # Xử lý textwords = text.lower().split()words = [w.strip('.,!?') for w in words] # Đếm frequencyword_count = {}for word in words: word_count[word] = word_count.get(word, 0) + 1 # Hiển thịprint("Word Frequency:")for word, count in sorted(word_count.items(), key=lambda x: x[1], reverse=True): print(f" {word:<15} {count}") # Top 3 wordstop_3 = sorted(word_count.items(), key=lambda x: x[1], reverse=True)[:3]print("\nTop 3 words:")for word, count in top_3: print(f" {word}: {count}")
4. Student Grade System
# Điểm học sinhstudents = { "Alice": [85, 90, 88], "Bob": [78, 82, 80], "Charlie": [92, 95, 90], "Diana": [88, 85, 87]} # Tính điểm trung bìnhprint("Student Grades:")for name, grades in students.items(): avg = sum(grades) / len(grades) print(f" {name:<10} Grades: {grades} Average: {avg:.2f}") # Tìm học sinh cao điểm nhấtbest_student = max(students.items(), key=lambda x: sum(x[1]) / len(x[1]))best_name, best_grades = best_studentbest_avg = sum(best_grades) / len(best_grades)print(f"\nBest student: {best_name} with average {best_avg:.2f}") # Thêm điểm mớistudents["Alice"].append(95)print(f"\nAlice's new grades: {students['Alice']}") # Học sinh pass (average >= 80)passed = {name: grades for name, grades in students.items() if sum(grades) / len(grades) >= 80}print(f"\nPassed students: {list(passed.keys())}")
5. Config Settings
# Application configconfig = { "app_name": "My App", "version": "1.0.0", "debug": True, "database": { "host": "localhost", "port": 5432, "name": "mydb" }, "features": { "auth": True, "email": True, "notifications": False }} # Access nested configdb_host = config["database"]["host"]print(f"Database host: {db_host}") # Check feature enabledif config["features"]["auth"]: print("Authentication enabled") # Update configconfig["debug"] = Falseconfig["database"]["port"] = 3306 # Display configprint("\nConfiguration:")for key, value in config.items(): if isinstance(value, dict): print(f"{key}:") for k, v in value.items(): print(f" {k}: {v}") else: print(f"{key}: {value}")
Bài Tập Thực Hành
Bài 1: Basic Operations
Tạo dictionary student với name, age, grade:
- Thêm email
- Update age
- Xóa grade
- Hiển thị tất cả keys và values
Bài 2: Merge Dictionaries
Gộp 2 dictionaries:
dict1 = {"a": 1, "b": 2}dict2 = {"b": 3, "c": 4}- Result:
{"a": 1, "b": 3, "c": 4}
Bài 3: Reverse Dictionary
Đảo key-value:
- Input:
{"a": 1, "b": 2, "c": 3} - Output:
{1: "a", 2: "b", 3: "c"}
Bài 4: Group By
Cho list students, group theo grade:
- Students:
[("Alice", "A"), ("Bob", "B"), ("Charlie", "A")] - Result:
{"A": ["Alice", "Charlie"], "B": ["Bob"]}
Bài 5: Shopping Cart
Tạo shopping cart với:
- Add item (name, price, quantity)
- Update quantity
- Remove item
- Calculate total
Tóm Tắt
✅ Dictionary: key-value pairs, unordered (3.7+ ordered), mutable
✅ Access: dict[key] hoặc dict.get(key, default)
✅ Add/Update: dict[key] = value hoặc dict.update()
✅ Remove: del, pop(), popitem(), clear()
✅ Methods: keys(), values(), items(), get(), setdefault()
✅ Loop: for key, value in dict.items()
✅ Check: key in dict
Bài Tiếp Theo
Remember:
- Keys phải immutable (string, number, tuple)
get()an toàn hơn[]khi key có thể không tồn tạiitems()để loop qua key-value pairs- Dictionary rất nhanh cho lookups (O(1))
- Dùng dictionaries cho mappings, configs, counters!