Khóa học
Dictionary (hay dict trong Python) là một cách lưu trữ phần tử tương tự như trong danh sách Python. Tuy nhiên, thay vì truy cập phần tử bằng chỉ số, bạn gán cho nó một khóa cố định và truy cập phần tử bằng khóa đó. Lúc này, bạn làm việc với cặp "khóa-giá trị", đôi khi là cấu trúc dữ liệu phù hợp hơn cho nhiều vấn đề so với danh sách đơn giản. Bạn sẽ thường xuyên phải làm việc với dictionary khi làm khoa học dữ liệu, vì vậy dictionary comprehension là kỹ năng bạn sẽ muốn thành thạo.
Trong hướng dẫn này:
- Trước hết, bạn sẽ thấy Python dictionary thực sự là gì và cách dùng hiệu quả.
- Tiếp theo, bạn sẽ tìm hiểu về Python dictionary comprehension: nó là gì, vì sao quan trọng, và cách nó có thể thay thế vòng lặp for và hàm lambda.
- Bạn sẽ học cách thêm điều kiện vào dictionary comprehension: làm việc với điều kiện if, nhiều điều kiện if, và cả câu lệnh if-else.
- Cuối cùng, bạn sẽ thấy nested dictionary comprehension là gì, cách sử dụng, và cách có thể viết lại bằng vòng lặp for.
Để tự mình chạy dễ dàng toàn bộ mã ví dụ trong hướng dẫn này, bạn có thể tạo miễn phí một sổ tay DataLab đã cài sẵn Python và chứa toàn bộ mẫu mã. Để luyện tập thêm về dictionary comprehension, hãy xem khóa học tương tác Python Toolbox của chúng tôi.
Python Dictionary là gì?
Dictionary trong Python là một tập hợp các phần tử được truy cập bằng một khóa cụ thể thay vì bằng chỉ số. Điều này có nghĩa là gì?
Hãy hình dung một cuốn từ điển trong đời thực. Khi cần tra nghĩa của một từ, bạn tìm bằng chính từ đó chứ không phải theo chỉ số có thể có của từ. Python dictionary hoạt động tương tự: Từ mà bạn đang tìm nghĩa là khóa, và nghĩa của từ là giá trị. Bạn không cần biết chỉ số của từ trong từ điển để tìm nghĩa của nó.
Khởi tạo dictionary trong Python
Bạn có thể khởi tạo một dictionary trong Python như sau:
a = {'apple': 'fruit', 'beetroot': 'vegetable', 'cake': 'dessert'}
a['doughnut'] = 'snack'
print(a['apple'])
fruit
print(a[0])
--------------------------------------------------------------------------- KeyError Traceback (most recent call last) <ipython-input-9-00d4a978143a> in <module>() ----> 1 print(a[0]) KeyError: 0
Đầu tiên, chúng ta tạo một dictionary tên a có ba cặp khóa-giá trị: 'apple': 'fruit', 'beetroot': 'vegetable', và 'cake': 'dessert'. Các khóa là chuỗi biểu thị tên mục, còn các giá trị là chuỗi biểu thị kiểu hoặc nhóm của mục.
Tiếp theo, ta thêm một cặp khóa-giá trị mới vào dictionary a với cú pháp a ['doughnut'] = 'snack'. Điều này thêm khóa 'doughnut' vào dictionary với giá trị tương ứng 'snack'.
Dòng thứ ba in ra giá trị gắn với khóa 'apple' trong dictionary a. Vì 'apple' là một khóa của dictionary, mã sẽ in ra giá trị 'fruit'.
Dòng thứ tư cố in giá trị gắn với khóa 0 trong dictionary a, vốn không phải là một khóa hợp lệ. Điều này dẫn đến KeyError, được ném ra khi cố truy cập một khóa không tồn tại trong dictionary.
Kiểu dữ liệu trong Python dictionary
Các phần tử trong một dictionary có thể thuộc bất kỳ kiểu dữ liệu nào. Xem thêm vài ví dụ dưới đây để quen tay:
Tạo dictionary a với bốn cặp khóa-giá trị:
a = {'one': 1, 'two': 'to', 'three': 3.0, 'four': [4,4.0]}
print(a)
Cập nhật giá trị gắn với khóa 'one' trong dictionary a thành 1.0.
# Update a dictionary
a['one'] = 1.0
print(a)
{'four': [4, 4.0], 'two': 'to', 'three': 3.0, 'one': 1.0}
Xóa cặp khóa-giá trị gắn với khóa 'one' khỏi dictionary a.
# Delete a single element
del a['one']
print(a)
{'four': [4, 4.0], 'two': 'to', 'three': 3.0}
Xóa tất cả cặp khóa-giá trị khỏi dictionary a bằng phương thức clear().
# Delete all elements in the dictionary
a.clear()
print(a)
{}
Xóa dictionary a bằng từ khóa del.
# Delete the dictionary
del a
print(a)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-12-701c9d6596da> in <module>()
1 del a #Deletes the dictionary
----> 2 print(a)
NameError: name 'a' is not defined
Điều quan trọng cần nhớ là khóa phải là duy nhất trong một dictionary; không cho phép trùng lặp. Tuy nhiên, khi có khóa trùng, thay vì báo lỗi, Python sẽ lấy lần xuất hiện cuối cùng của khóa là hợp lệ và đơn giản bỏ qua cặp khóa-giá trị đầu tiên. Tự kiểm chứng nhé:
sweet_dict = {'a1': 'cake', 'a2':'cookie', 'a1': 'icecream'}
print(sweet_dict['a1'])
icecream
Python Dictionary Comprehension
Dictionary comprehension là phương pháp chuyển đổi một dictionary này thành một dictionary khác. Trong quá trình chuyển đổi, các phần tử trong dictionary gốc có thể được đưa vào có điều kiện trong dictionary mới, và mỗi phần tử có thể được biến đổi khi cần.
Một comprehension tốt có thể giúp mã của bạn biểu đạt rõ ràng hơn và do đó dễ đọc hơn. Mấu chốt là đừng để chúng trở nên quá phức tạp khiến bạn đau đầu khi cố giải mã chúng đang làm gì. Hãy giữ tinh thần "dễ đọc".
Cách thực hiện dictionary comprehension trong Python là truy cập được các đối tượng key và value của một dictionary.
Làm sao để làm được điều này?
Python đã hỗ trợ sẵn! Bạn có thể dùng các phương thức tích hợp sau:
dict1 = {'a': 1, 'b': 2, 'c': 3, 'd': 4}
# Put all keys of `dict1` in a list and returns the list
dict1.keys()
dict_keys(['c', 'd', 'a', 'b'])
# Put all values saved in `dict1` in a list and returns the list
dict1.values()
dict_values([3, 4, 1, 2])
Đoạn mã trên tạo một Python dictionary tên dict1 với bốn cặp khóa-giá trị. Phương thức keys() được gọi trên dictionary, trả về một đối tượng view chứa tất cả các khóa trong dictionary.
Phương thức values() cũng được gọi, trả về một đối tượng view chứa tất cả các giá trị trong dictionary.
Cả hai đối tượng view này có hành vi giống tập hợp và có thể dùng để thực hiện các phép toán trên tập hợp với khóa và giá trị tương ứng.
Lưu ý rằng thứ tự của các khóa và giá trị trong các đối tượng view không được đảm bảo giống với thứ tự chúng được thêm vào dictionary.
Biến đổi giá trị cơ bản
Bắt đầu với một ví dụ dictionary comprehension đơn giản:
dict1 = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
# Double each value in the dictionary
double_dict1 = {k:v*2 for (k,v) in dict1.items()}
print(double_dict1)
{'e': 10, 'a': 2, 'c': 6, 'b': 4, 'd': 8}
Trong đoạn comprehension trên, chúng ta tạo một dictionary mới double_dict1 từ dict1 bằng cách đơn giản là nhân đôi mỗi giá trị trong đó.
Bạn cũng có thể thay đổi các khóa. Ví dụ, hãy tạo dictionary giống ở trên nhưng đổi cả tên khóa.
dict1_keys = {k*2:v for (k,v) in dict1.items()}
print(dict1_keys)
{'dd': 4, 'ee': 5, 'aa': 1, 'bb': 2, 'cc': 3}
Sử dụng phương thức items()
Bây giờ bạn đã biết cách truy cập tất cả khóa và giá trị trong một dictionary. Bạn cũng có thể truy cập từng cặp khóa-giá trị bằng phương thức items():
dict1.items()
dict_items([('c', 3), ('d', 4), ('a', 1), ('b', 2)])
Đây là mẫu tổng quát bạn có thể theo cho dictionary comprehension trong Python:
dict_variable = {key:value for (key,value) in dictonary.items()}
Đây có thể xem là mẫu cơ bản và đơn giản nhất. Nó có thể trở nên phức tạp dần khi bạn thêm các điều kiện vào.
Sử dụng phương thức fromkeys()
Python cũng cung cấp phương thức fromkeys(), cho phép bạn tạo dictionary với cùng một giá trị cho một tập khóa xác định. Cách này hữu ích khi khởi tạo dictionary với các giá trị mặc định. Xem thử:
# Create a dictionary with keys ranging from 0 to 4, all set to True
my_dict = dict.fromkeys(range(5), True)
print(my_dict)
{0: True, 1: True, 2: True, 3: True, 4: True}
Trong ví dụ này, phương thức fromkeys() tạo một dictionary với các khóa là số từ 0 đến 4, và mỗi khóa được gán giá trị True. Cách tiếp cận này giúp đơn giản hóa các tác vụ như khởi tạo dictionary để cập nhật hoặc xử lý sau này.
Vì sao dùng Dictionary Comprehension?
Dictionary comprehension là một khái niệm mạnh mẽ và có thể dùng để thay thế vòng lặp for và hàm lambda. Tuy nhiên, không phải mọi vòng lặp for đều có thể viết lại thành dictionary comprehension, nhưng mọi dictionary comprehension đều có thể viết lại bằng vòng lặp for.
Xét bài toán sau: bạn muốn tạo một dictionary mới trong đó khóa là các số chia hết cho 2 trong khoảng 0-10, và giá trị là bình phương của số đó.
Hãy xem cách giải cùng một bài toán bằng vòng lặp for và dictionary comprehension:
numbers = range(10)
new_dict_for = {}
# Add values to `new_dict` using for loop
for n in numbers:
if n%2==0:
new_dict_for[n] = n**2
print(new_dict_for)
{0: 0, 8: 64, 2: 4, 4: 16, 6: 36}
# Use dictionary comprehension
new_dict_comp = {n:n**2 for n in numbers if n%2 == 0}
print(new_dict_comp)
{0: 0, 8: 64, 2: 4, 4: 16, 6: 36}
Thay thế vòng lặp for
Vòng lặp for được dùng để lặp lại một thao tác hoặc một khối lệnh trong chương trình một số lần nhất định. Tuy nhiên, vòng lặp for lồng nhau (for trong for) có thể rối và phức tạp. Dictionary comprehension tốt hơn trong những tình huống như vậy và có thể giúp mã dễ đọc, dễ hiểu hơn.
Mẹo: xem hướng dẫn Loops in Python của DataCamp để biết thêm về vòng lặp trong Python.
Thay thế hàm lambda
Hàm lambda là cách tạo các hàm nhỏ ẩn danh. Chúng là những hàm không có tên. Các hàm này thường chỉ dùng tại nơi chúng được tạo. Lambda chủ yếu dùng kết hợp với các hàm filter(), map() và reduce().
Hãy xem ví dụ hàm lambda cùng với hàm map():
# Initialize `fahrenheit` dictionary
fahrenheit = {'t1':-30, 't2':-20, 't3':-10, 't4':0}
#Get the corresponding `celsius` values
celsius = list(map(lambda x: (float(5)/9)*(x-32), fahrenheit.values()))
#Create the `celsius` dictionary
celsius_dict = dict(zip(fahrenheit.keys(), celsius))
print(celsius_dict)
{'t2': -28.88888888888889, 't3': -23.333333333333336, 't1': -34.44444444444444, 't4': -17.77777777777778}
Ví dụ chi tiết về Python Dictionary Comprehension
Xem một tình huống khác: bạn muốn chuyển đổi một dictionary nhiệt độ Fahrenheit sang Celsius.
Hãy phân tích: trước hết, bạn cần xác định công thức toán học chuyển đổi từ Fahrenheit sang Celsius.
Trong mã, việc này được thực hiện với hàm lambda. Bạn truyền hàm này làm đối số cho hàm map(), hàm này áp dụng phép biến đổi cho từng phần tử trong danh sách fahrenheit.values().
Nhớ phương thức values() chứ? Nó trả về danh sách chứa các phần tử được lưu trong dictionary.
Giờ bạn có một danh sách giá trị nhiệt độ theo Celsius, nhưng yêu cầu là một dictionary.
Python có hàm dựng sẵn zip() để duyệt qua các phần tử của các iterator và gom chúng lại. Bạn có thể đọc thêm về hàm zip() trong ví dụ Python này.
Trong ví dụ trên, hàm zip gom phần tử từ fahrenheit.keys() và danh sách celsius, tạo ra cặp khóa-giá trị mà bạn có thể kết hợp thành dictionary bằng hàm dict, cho ra kết quả mong muốn.
Bây giờ, hãy thử giải cùng bài toán bằng dictionary comprehension:
# Initialize the `fahrenheit` dictionary
fahrenheit = {'t1': -30,'t2': -20,'t3': -10,'t4': 0}
# Get the corresponding `celsius` values and create the new dictionary
celsius = {k:(float(5)/9)*(v-32) for (k,v) in fahrenheit.items()}
print(celsius_dict)
{'t2': -28.88888888888889, 't3': -23.333333333333336, 't1': -34.44444444444444, 't4': -17.77777777777778}
Dưới đây là phần phân tích những gì chúng ta đã tạo ở đoạn mã trên:
-
Tạo một dictionary tên
fahrenheitvới bốn cặp khóa-giá trị biểu thị nhiệt độ theo Fahrenheit. -
Định nghĩa một dictionary mới gọi là
celsius. -
Dùng dictionary comprehension để lặp qua dictionary
fahrenheitvà chuyển đổi nhiệt độ Fahrenheit sang Celsius theo công thức(5/9) * (F-32). -
Với mỗi cặp khóa-giá trị trong
fahrenheit, khóa được gán cho biếnkvà giá trị cho biếnv. -
Giá trị nhiệt độ Celsius tương ứng với mỗi nhiệt độ Fahrenheit được tính theo công thức trên và được thêm vào dictionary
celsiusdưới dạng cặp khóa-giá trị. -
Dictionary
celsiusthu được được in ra màn hình.
Như bạn thấy, bài toán có thể giải bằng một dòng mã với dictionary comprehension so với quy trình hai bước và phải hiểu cách hoạt động của ba hàm (lambda, map() và zip()) trong cách triển khai đầu tiên.
Hơn nữa, giải pháp bằng dictionary comprehension trực quan và dễ hiểu. Do đó, dictionary comprehension có thể là lựa chọn thay thế tốt cho hàm lambda.
Thêm điều kiện vào Dictionary Comprehension
Khi giải quyết vấn đề, bạn thường cần thêm điều kiện vào lời giải. Hãy khám phá cách thêm điều kiện vào dictionary comprehension để khiến nó mạnh mẽ hơn.
Điều kiện if
Giả sử bạn cần tạo một dictionary mới từ dictionary đã cho nhưng chỉ lấy các mục có giá trị lớn hơn 2. Điều này có nghĩa là bạn cần thêm điều kiện vào mẫu cơ bản ở trên...
dict1 = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
# Check for items greater than 2
dict1_cond = {k:v for (k,v) in dict1.items() if v>2}
print(dict1_cond)
{'e': 5, 'c': 3, 'd': 4}
Không quá khó! Nhưng nếu bạn có nhiều điều kiện thì sao?
Nhiều điều kiện if
Trong bài toán trên, nếu bạn không chỉ cần lấy các mục có giá trị lớn hơn 2 mà còn cần kiểm tra xem chúng có là bội số của 2 hay không cùng lúc?
dict1_doubleCond = {k:v for (k,v) in dict1.items() if v>2 if v%2 == 0}
print(dict1_doubleCond)
{'d': 4}
Giải pháp để thêm nhiều điều kiện đơn giản là nối các điều kiện liên tiếp trong comprehension. Tuy nhiên, bạn cần cẩn trọng với mục tiêu của bài toán. Hãy nhớ rằng các câu if liên tiếp hoạt động như thể giữa chúng có các mệnh đề and.
Xem thêm một ví dụ với ba điều kiện:
dict1 = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f':6}
dict1_tripleCond = {k:v for (k,v) in dict1.items() if v>2 if v%2 == 0 if v%3 == 0}
print(dict1_tripleCond)
{'f': 6}
Trong vòng lặp for, điều này tương ứng với:
dict1_tripleCond = {}
for (k,v) in dict1.items():
if (v>=2 and v%2 == 0 and v%3 == 0):
dict1_tripleCond[k] = v
print(dict1_tripleCond)
{'f': 6}
Điều kiện if-else
Xử lý điều kiện if-else cũng dễ với dictionary comprehension. Xem ví dụ sau để tự kiểm chứng:
dict1 = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f':6}
# Identify odd and even entries
dict1_tripleCond = {k:('even' if v%2==0 else 'odd') for (k,v) in dict1.items()}
print(dict1_tripleCond)
{'f': 'even', 'c': 'odd', 'b': 'even', 'd': 'even', 'e': 'odd', 'a': 'odd'}
Nested dictionary comprehension
Lồng nhau (nesting) là một khái niệm lập trình trong đó dữ liệu được tổ chức theo lớp hoặc đối tượng chứa các đối tượng tương tự khác. Bạn hẳn đã thấy cấu trúc if lồng nhau, tức là một điều kiện if nằm trong một điều kiện if khác.
Tương tự, dictionary có thể lồng nhau, và do đó comprehension của chúng cũng có thể lồng nhau. Hãy xem điều này nghĩa là gì:
nested_dict = {'first':{'a':1}, 'second':{'b':2}}
float_dict = {outer_k: {float(inner_v) for (inner_k, inner_v) in outer_v.items()} for (outer_k, outer_v) in nested_dict.items()}
print(float_dict)
{'first': {1.0}, 'second': {2.0}}
Đây là một ví dụ về dictionary lồng nhau. nested_dict là dictionary có các khóa: first và second, với giá trị là các đối tượng dictionary. Mã làm việc với các giá trị dictionary bên trong, chuyển chúng sang float, rồi kết hợp khóa ngoài với các giá trị float bên trong mới thành một dictionary mới.
Đoạn mã cũng có một dictionary comprehension lồng nhau, tức dictionary comprehension nằm trong một comprehension khác. Khi lồng nhau, comprehension có thể khá khó đọc và khó hiểu, đi ngược lại mục đích dùng comprehension ngay từ đầu.
Khi cấu trúc dictionary bạn làm việc trở nên phức tạp, dictionary comprehension cũng sẽ phức tạp theo. Với những tình huống như vậy, bạn có thể nên tránh dùng comprehension rối rắm trong mã.
Lưu ý rằng bạn có thể viết lại đoạn mã trên bằng vòng lặp for lồng nhau:
nested_dict = {'first':{'a':1}, 'second':{'b':2}}
for (outer_k, outer_v) in nested_dict.items():
for (inner_k, inner_v) in outer_v.items():
outer_v.update({inner_k: float(inner_v)})
nested_dict.update({outer_k:outer_v})
print(nested_dict)
{'first': {'a': 1.0}, 'second': {'b': 2.0}}
Lời kết
Hy vọng bạn đã hiểu về dictionary trong Python, khái niệm comprehension, cũng như lý do và bối cảnh mà Python dictionary comprehension hữu ích.
Luyện tập sẽ giúp Python của bạn tốt hơn! Xem thêm một số mẹo và thủ thuật Python để cải thiện mã, hoặc theo học lộ trình Python Data Fundamentals để làm chủ những nội dung quan trọng nhất.
Câu hỏi thường gặp về Python Dictionary Comprehension
Dictionary comprehension trong Python là gì?
Dictionary comprehension là cách ngắn gọn và dễ đọc để tạo dictionary trong Python. Nó cung cấp một cách để tạo dictionary mới từ một đối tượng có thể lặp như list, tuple hoặc set.
Cú pháp của dictionary comprehension trong Python là gì?
Cú pháp cho dictionary comprehension trong Python như sau: {key:value for (key,value) in iterable}
Làm sao tạo dictionary từ list bằng dictionary comprehension trong Python?
Bạn có thể tạo dictionary từ một list bằng dictionary comprehension trong Python bằng cách lặp qua list và đặt các phần tử của list làm khóa và giá trị trong dictionary mới.
Tôi có thể dùng câu lệnh điều kiện trong dictionary comprehension trong Python không?
Có, bạn có thể dùng câu lệnh điều kiện trong dictionary comprehension trong Python để lọc bỏ một số phần tử nhất định.
Lợi ích của việc dùng dictionary comprehension trong Python là gì?
Lợi ích của việc dùng dictionary comprehension trong Python là ngắn gọn, dễ đọc và giảm lượng mã cần thiết để tạo dictionary. Nó cũng cho phép lọc và biến đổi phần tử của dictionary trong một dòng mã.
Tôi đã làm việc trong nhiều ngành và đảm nhiệm nhiều vai trò: nhà phát triển phần mềm, nhà nghiên cứu học máy, nhà khoa học dữ liệu, quản lý sản phẩm. Nhưng cốt lõi của tất cả, tôi là một lập trình viên yêu thích học hỏi và chia sẻ kiến thức!
