Bài 6.4. Python - Lồng ghép (Nesting)

Bài 6.4. Python - Lồng ghép (Nesting)
Đôi khi bạn sẽ muốn lưu trữ nhiều từ điển trong một danh sách, hoặc một danh sách các mục làm giá trị trong một từ điển. Điều này được gọi là lồng ghép. Bạn có thể lồng từ điển bên trong một danh sách, một danh sách các mục bên trong một từ điển, hoặc thậm chí là một từ điển bên trong một từ điển khác. Lồng ghép là một tính năng mạnh mẽ, như các ví dụ sau sẽ minh họa.
Danh sách các từ điển
Từ điển alien_0
chứa nhiều thông tin về một người ngoài hành tinh, nhưng nó không có chỗ để lưu trữ thông tin về một người ngoài hành tinh thứ hai, chứ chưa nói đến một màn hình đầy người ngoài hành tinh. Làm thế nào bạn có thể quản lý một đội quân người ngoài hành tinh? Một cách là tạo một danh sách các người ngoài hành tinh trong đó mỗi người ngoài hành tinh là một từ điển chứa thông tin về người ngoài hành tinh đó. Ví dụ, mã sau đây xây dựng một danh sách ba người ngoài hành tinh:
alien_0 = {'color': 'green', 'points': 5}
alien_1 = {'color': 'yellow', 'points': 10}
alien_2 = {'color': 'red', 'points': 15}
aliens = [alien_0, alien_1, alien_2]
for alien in aliens:
print(alien)
Chúng ta đầu tiên tạo ba từ điển, mỗi từ điển đại diện cho một người ngoài hành tinh khác nhau. Chúng ta lưu trữ mỗi từ điển này trong một danh sách gọi là aliens
. Cuối cùng, chúng ta lặp qua danh sách và in ra mỗi người ngoài hành tinh:
{'color': 'green', 'points': 5}
{'color': 'yellow', 'points': 10}
{'color': 'red', 'points': 15}
Một ví dụ thực tế hơn sẽ liên quan đến nhiều hơn ba người ngoài hành tinh với mã tự động tạo ra mỗi người ngoài hành tinh. Trong ví dụ sau, chúng ta sử dụng range()
để tạo một đội quân 30 người ngoài hành tinh:
# Tạo một danh sách trống để lưu trữ người ngoài hành tinh.
aliens = []
# Tạo 30 người ngoài hành tinh màu xanh lá cây.
for alien_number in range(30):
new_alien = {'color': 'green', 'points': 5, 'speed': 'slow'}
aliens.append(new_alien)
# Hiển thị 5 người ngoài hành tinh đầu tiên.
for alien in aliens[:5]:
print(alien)
print("...")
# Hiển thị số lượng người ngoài hành tinh đã được tạo ra.
print(f"Total number of aliens: {len(aliens)}")
Ví dụ này bắt đầu với một danh sách trống để chứa tất cả các người ngoài hành tinh sẽ được tạo ra. Hàm range()
trả về một chuỗi các số, chỉ cho Python biết chúng ta muốn vòng lặp lặp lại bao nhiêu lần. Mỗi lần vòng lặp chạy, chúng ta tạo một người ngoài hành tinh mới và sau đó thêm mỗi người ngoài hành tinh mới vào danh sách aliens
. Chúng ta sử dụng một lát cắt để in ra năm người ngoài hành tinh đầu tiên, và cuối cùng, chúng ta in ra độ dài của danh sách để chứng minh rằng chúng ta đã thực sự tạo ra đội quân 30 người ngoài hành tinh:
{'color': 'green', 'points': 5, 'speed': 'slow'}
{'color': 'green', 'points': 5, 'speed': 'slow'}
{'color': 'green', 'points': 5, 'speed': 'slow'}
{'color': 'green', 'points': 5, 'speed': 'slow'}
{'color': 'green', 'points': 5, 'speed': 'slow'}
...
Total number of aliens: 30
Những người ngoài hành tinh này đều có cùng đặc điểm, nhưng Python coi mỗi người là một đối tượng riêng biệt, cho phép chúng ta sửa đổi từng người ngoài hành tinh một cách riêng lẻ.
Làm thế nào bạn có thể làm việc với một nhóm người ngoài hành tinh như thế này? Hãy tưởng tượng rằng một khía cạnh của trò chơi có một số người ngoài hành tinh thay đổi màu sắc và di chuyển nhanh hơn khi trò chơi tiến triển. Khi đến lúc thay đổi màu sắc, chúng ta có thể sử dụng một vòng lặp for
và một câu lệnh if
để thay đổi màu sắc của người ngoài hành tinh. Ví dụ, để thay đổi ba người ngoài hành tinh đầu tiên thành màu vàng, người ngoài hành tinh tốc độ trung bình có giá trị 10 điểm mỗi người, chúng ta có thể làm như sau:
# Tạo một danh sách trống để lưu trữ người ngoài hành tinh.
aliens = []
# Tạo 30 người ngoài hành tinh màu xanh lá cây.
for alien_number in range(30):
new_alien = {'color': 'green', 'points': 5, 'speed': 'slow'}
aliens.append(new_alien)
for alien in aliens[:3]:
if alien['color'] == 'green':
alien['color'] = 'yellow'
alien['speed'] = 'medium'
alien['points'] = 10
# Hiển thị 5 người ngoài hành tinh đầu tiên.
for alien in aliens[:5]:
print(alien)
print("...")
Vì chúng ta muốn sửa đổi ba người ngoài hành tinh đầu tiên, chúng ta lặp qua một lát cắt chỉ bao gồm ba người ngoài hành tinh đầu tiên. Tất cả các người ngoài hành tinh đều màu xanh lá cây bây giờ, nhưng điều đó sẽ không luôn luôn như vậy, vì vậy chúng ta viết một câu lệnh if
để đảm bảo rằng chúng ta chỉ sửa đổi những người ngoài hành tinh màu xanh lá cây. Nếu người ngoài hành tinh là màu xanh lá cây, chúng ta thay đổi màu sắc thành 'yellow', tốc độ thành 'medium', và giá trị điểm thành 10, như được hiển thị trong đầu ra sau:
{'color': 'yellow', 'points': 10, 'speed': 'medium'}
{'color': 'yellow', 'points': 10, 'speed': 'medium'}
{'color': 'yellow', 'points': 10, 'speed': 'medium'}
{'color': 'green', 'points': 5, 'speed': 'slow'}
{'color': 'green', 'points': 5, 'speed': 'slow'}
...
Bạn có thể mở rộng vòng lặp này bằng cách thêm một khối elif
để biến những người ngoài hành tinh màu vàng thành màu đỏ, di chuyển nhanh với giá trị 15 điểm mỗi người. Không cần hiển thị toàn bộ chương trình một lần nữa, vòng lặp đó sẽ trông như thế này:
for alien in aliens[:3]:
if alien['color'] == 'green':
alien['color'] = 'yellow'
alien['speed'] = 'medium'
alien['points'] = 10
elif alien['color'] == 'yellow':
alien['color'] = 'red'
alien['speed'] = 'fast'
alien['points'] = 15
Thường thì bạn sẽ lưu trữ một số từ điển trong một danh sách khi mỗi từ điển chứa nhiều loại thông tin về một đối tượng. Ví dụ, bạn có thể tạo một từ điển cho mỗi người dùng trên một trang web, như chúng ta đã làm trong user.py
, và lưu trữ các từ điển riêng lẻ trong một danh sách gọi là users
. Tất cả các từ điển trong danh sách nên có cấu trúc giống hệt nhau, vì vậy bạn có thể lặp qua danh sách và làm việc với từng đối tượng từ điển theo cùng một cách.
Danh sách trong từ điển
Thay vì đặt một từ điển bên trong một danh sách, đôi khi hữu ích để đặt một danh sách bên trong một từ điển. Ví dụ, hãy xem xét cách bạn có thể mô tả một chiếc pizza mà ai đó đang đặt hàng. Nếu bạn chỉ sử dụng một danh sách, tất cả những gì bạn có thể thực sự lưu trữ là một danh sách các lớp phủ của pizza. Với một từ điển, một danh sách các lớp phủ có thể chỉ là một khía cạnh của chiếc pizza mà bạn đang mô tả.
Trong ví dụ sau, hai loại thông tin được lưu trữ cho mỗi chiếc pizza: loại vỏ và danh sách các lớp phủ. Danh sách các lớp phủ là một giá trị liên kết với khóa 'toppings'. Để sử dụng các mục trong danh sách, chúng ta đưa tên của từ điển và khóa 'toppings', như chúng ta sẽ làm với bất kỳ giá trị nào trong từ điển. Thay vì trả về một giá trị duy nhất, chúng ta nhận được một danh sách các lớp phủ:
# Lưu trữ thông tin về một chiếc pizza đang được đặt hàng.
pizza = {
'crust': 'thick',
'toppings': ['mushrooms', 'extra cheese'],
}
# Tóm tắt đơn hàng.
print(f"You ordered a {pizza['crust']}-crust pizza with the following toppings:")
for topping in pizza['toppings']:
print(f"\t{topping}")
Chúng ta bắt đầu với một từ điển chứa thông tin về một chiếc pizza đã được đặt hàng. Một khóa trong từ điển là 'crust', và giá trị liên kết là chuỗi 'thick'. Khóa tiếp theo, 'toppings', có một danh sách làm giá trị của nó lưu trữ tất cả các lớp phủ được yêu cầu. Chúng ta tóm tắt đơn hàng trước khi làm chiếc pizza. Khi bạn cần chia nhỏ một dòng dài trong lệnh print()
, hãy chọn một điểm thích hợp để chia dòng đang được in, và kết thúc dòng bằng một dấu ngoặc kép. Thụt lề dòng tiếp theo, thêm một dấu ngoặc kép mở, và tiếp tục chuỗi. Python sẽ tự động kết hợp tất cả các chuỗi mà nó tìm thấy bên trong dấu ngoặc đơn. Để in các lớp phủ, chúng ta viết một vòng lặp for
. Để truy cập danh sách các lớp phủ, chúng ta sử dụng khóa 'toppings', và Python lấy danh sách các lớp phủ từ từ điển.
Đầu ra sau tóm tắt chiếc pizza mà chúng ta dự định làm:
You ordered a thick-crust pizza with the following toppings:
mushrooms
extra cheese
Bạn có thể lồng một danh sách bên trong một từ điển bất cứ khi nào bạn muốn nhiều hơn một giá trị được liên kết với một khóa duy nhất trong một từ điển. Trong ví dụ trước về các ngôn ngữ lập trình yêu thích, nếu chúng ta lưu trữ các câu trả lời của mỗi người trong một danh sách, mọi người có thể chọn nhiều hơn một ngôn ngữ yêu thích. Khi chúng ta lặp qua từ điển, giá trị liên kết với mỗi người sẽ là một danh sách các ngôn ngữ thay vì một ngôn ngữ duy nhất. Bên trong vòng lặp for
của từ điển, chúng ta sử dụng một vòng lặp for
khác để chạy qua danh sách các ngôn ngữ liên kết với mỗi người:
favorite_languages = {
'jen': ['python', 'rust'],
'sarah': ['c'],
'edward': ['rust', 'go'],
'phil': ['python', 'haskell'],
}
for name, languages in favorite_languages.items():
print(f"\n{name.title()}'s favorite languages are:")
for language in languages:
print(f"\t{language.title()}")
Giá trị liên kết với mỗi tên trong favorite_languages
bây giờ là một danh sách. Lưu ý rằng một số người có một ngôn ngữ yêu thích và những người khác có nhiều ngôn ngữ yêu thích. Khi chúng ta lặp qua từ điển, chúng ta sử dụng biến languages
để giữ mỗi giá trị từ từ điển, vì chúng ta biết rằng mỗi giá trị sẽ là một danh sách. Bên trong vòng lặp từ điển chính, chúng ta sử dụng một vòng lặp for
khác để chạy qua danh sách các ngôn ngữ yêu thích của mỗi người. Bây giờ mỗi người có thể liệt kê bao nhiêu ngôn ngữ yêu thích tùy thích:
Jen's favorite languages are:
Python
Rust
Sarah's favorite languages are:
C
Edward's favorite languages are:
Rust
Go
Phil's favorite languages are:
Python
Haskell
Để tinh chỉnh chương trình này hơn nữa, bạn có thể bao gồm một câu lệnh if
ở đầu vòng lặp for
của từ điển để xem liệu mỗi người có nhiều hơn một ngôn ngữ yêu thích bằng cách kiểm tra giá trị của len(languages)
. Nếu một người có nhiều hơn một ngôn ngữ yêu thích, đầu ra sẽ giữ nguyên. Nếu người đó chỉ có một ngôn ngữ yêu thích, bạn có thể thay đổi cách diễn đạt để phản ánh điều đó. Ví dụ, bạn có thể nói, "Ngôn ngữ yêu thích của Sarah là C."
Từ điển trong từ điển
Bạn có thể lồng một từ điển bên trong một từ điển khác, nhưng mã của bạn có thể trở nên phức tạp nhanh chóng khi bạn làm điều đó. Ví dụ, nếu bạn có nhiều người dùng cho một trang web, mỗi người có một tên người dùng duy nhất, bạn có thể sử dụng tên người dùng làm khóa trong một từ điển. Bạn có thể lưu trữ thông tin về mỗi người dùng bằng cách sử dụng một từ điển làm giá trị liên kết với tên người dùng của họ. Trong danh sách sau, chúng ta lưu trữ ba mẩu thông tin về mỗi người dùng: tên đầu tiên, họ và địa điểm của họ. Chúng ta sẽ truy cập thông tin này bằng cách lặp qua các tên người dùng và từ điển thông tin liên kết với mỗi tên người dùng:
users = {
'aeinstein': {
'first': 'albert',
'last': 'einstein',
'location': 'princeton',
},
'mcurie': {
'first': 'marie',
'last': 'curie',
'location': 'paris',
},
}
for username, user_info in users.items():
print(f"\nUsername: {username}")
full_name = f"{user_info['first']} {user_info['last']}"
location = user_info['location']
print(f"\tFull name: {full_name.title()}")
print(f"\tLocation: {location.title()}")
Chúng ta đầu tiên định nghĩa một từ điển gọi là users
với hai khóa: một cho tên người dùng 'aeinstein' và 'mcurie'. Giá trị liên kết với mỗi khóa là một từ điển bao gồm tên đầu tiên, họ và địa điểm của mỗi người dùng. Sau đó, chúng ta lặp qua từ điển users
. Python gán mỗi khóa cho biến username
, và từ điển liên kết với mỗi tên người dùng được gán cho biến user_info
. Khi đã vào bên trong vòng lặp từ điển chính, chúng ta in ra tên người dùng.
Sau đó, chúng ta bắt đầu truy cập từ điển bên trong. Biến user_info
, chứa từ điển thông tin người dùng, có ba khóa: 'first', 'last', và 'location'. Chúng ta sử dụng mỗi khóa để tạo ra một tên đầy đủ và địa điểm được định dạng gọn gàng cho mỗi người, và sau đó in ra một bản tóm tắt về những gì chúng ta biết về mỗi người dùng:
Username: aeinstein
Full name: Albert Einstein
Location: Princeton
Username: mcurie
Full name: Marie Curie
Location: Paris
Lưu ý rằng cấu trúc của từ điển của mỗi người dùng là giống hệt nhau. Mặc dù không bắt buộc bởi Python, cấu trúc này làm cho các từ điển lồng nhau dễ làm việc hơn. Nếu từ điển của mỗi người dùng có các khóa khác nhau, mã bên trong vòng lặp for
sẽ phức tạp hơn.
Comments