[ATBS2nd]Chương 1 - Python cơ bản - Phần 18

Chào các bạn,
Chúng ta lại tiếp tục với serie Python cơ bản. Trong phần này chúng ta sẽ học một dạng dữ liệu hết sức quan trọng của Python là kiểu dữ liệu từ điển(dictionary).
Trong phần này, chúng tôi sẽ đề cập đến kiểu dữ liệu từ điển, cung cấp một cách linh hoạt để truy cập và sắp xếp dữ liệu. Sau đó, kết hợp từ điển với kiến thức của bạn về các danh sách từ phần trước, bạn sẽ học cách tạo cấu trúc dữ liệu để mô hình hóa một bảng tic-tac-toe.
Kiểu dữ liệu từ điển(dictionary)
Giống như một danh sách, một từ điển là một bộ sưu tập có thể thay đổi của nhiều giá trị. Nhưng không giống như các chỉ mục cho danh sách, các chỉ mục cho từ điển có thể sử dụng nhiều loại dữ liệu khác nhau, không chỉ các số nguyên. Các chỉ mục cho từ điển được gọi là khóa và một khóa có giá trị liên quan được gọi là cặp khóa-giá trị.
Trong mã, một từ điển được gõ bằng dấu ngoặc, {}. Nhập thông tin sau vào command line:
`

myCat = {‘size’: ‘fat’, ‘color’: ‘gray’, ‘disposition’: ‘loud’}

`
Ta thấy từ điển myCat có các khóa là size, color, disposition và có các giá trị là fat, gray và loud. Chúng ta có thể truy nhập các giá trị qua khóa của chúng.

>>> myCat['size']
'fat'
>>> 'My cat has ' + myCat['color'] + ' fur.'
'My cat has gray fur.'

Từ điển vẫn có thể sử dụng các giá trị số nguyên làm khóa, giống như danh sách sử dụng số nguyên cho chỉ mục, nhưng chúng không phải bắt đầu từ 0 và có thể là bất kỳ số nào.
`

spam = {12345: ‘Luggage Combination’, 42: ‘The Answer’}

`
Từ điển vs danh sách
Không giống như danh sách, các mục trong từ điển là không có thứ tự. Mục đầu tiên trong danh sách có tên là spam sẽ là spam[0]. Nhưng không có mục nào đầu tiên trong một cuốn từ điển.
Mặc dù thứ tự của các mục quan trọng để xác định xem hai danh sách có giống nhau hay không, không quan trọng thứ tự các cặp khóa-giá trị được nhập trong từ điển. Nhập thông tin sau vào command line:

>>> spam = ['cats', 'dogs', 'moose']
>>> bacon = ['dogs', 'moose', 'cats']
>>> spam == bacon
False
>>> eggs = {'name': 'Zophie', 'species': 'cat', 'age': '8'}
>>> ham = {'species': 'cat', 'age': '8', 'name': 'Zophie'}
>>> eggs == ham
True

Bởi vì từ điển không được đặt hàng, chúng có thể được cắt lát như danh sách. Cố gắng truy cập một khóa không tồn tại trong từ điển sẽ dẫn đến thông báo lỗi KeyError, giống như một danh sách thông báo lỗi trong phạm vi phạm vi phạm IndexError. Nhập thông tin sau vào command line và thông báo thông báo lỗi hiển thị vì không có phím ‘color’:

>>> spam = {'name': 'Zophie', 'age': 7}
>>> spam['color']
Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    spam['color']
KeyError: 'color'

Mặc dù từ điển không được sắp xếp, nhưng thực tế là bạn có thể có các giá trị tùy ý cho các khóa cho phép bạn sắp xếp dữ liệu của mình theo những cách mạnh mẽ. Giả sử bạn muốn chương trình của mình lưu trữ dữ liệu về ngày sinh nhật của bạn bè. Bạn có thể sử dụng một từ điển với tên là khóa và ngày sinh làm giá trị. Mở một cửa sổ soạn thảo văn bản mới và nhập mã sau đây. Lưu nó dưới dạng birthday.py.

birthdays = {'Alice': 'Apr 1', 'Bob': 'Dec 12', 'Carol': 'Mar 4'}
while True:
	print('Enter a name: (blank to quit)')
	name = input()
	if name == '':
		break
	if name in birthdays:
		print(birthdays[name] + ' is the birthday of ' + name)
	else:
		print('I do not have birthday information for ' + name)
		print('What is their birthday?')
		bday = input()
		birthdays[name] = bday
		print('Birthday database updated.')

Bạn tạo một từ điển ban đầu và lưu trữ nó trong birthdays. Bạn có thể xem tên đã nhập có tồn tại dưới dạng khóa trong từ điển với từ khóa in không, giống như bạn đã làm cho danh sách. Nếu tên trong từ điển, bạn truy cập giá trị được liên kết bằng dấu ngoặc vuông; nếu không, bạn có thể thêm nó bằng cú pháp dấu ngoặc vuông tương tự kết hợp với toán tử gán.
Khi bạn chạy chương trình này, nó sẽ trông như thế này:

Enter a name: (blank to quit)
Alice
Apr 1 is the birthday of Alice
Enter a name: (blank to quit)
Eve
I do not have birthday information for Eve
What is their birthday?
Dec 5
Birthday database updated.
Enter a name: (blank to quit)
Eve
Dec 5 is the birthday of Eve
Enter a name: (blank to quit)

Từ điển được sắp xếp trong Python 3.7
Mặc dù họ vẫn chưa đặt thứ tự và không có cặp khóa-giá trị đầu tiên, nhưng từ điển trong Python 3.7 trở lên sẽ ghi nhớ thứ tự chèn của các cặp giá trị khóa nếu bạn tạo giá trị chuỗi từ chúng. Ví dụ: chú ý thứ tự của các mục trong danh sách được tạo từ từ điển eggs và ham khớp với thứ tự mà chúng được nhập vào:

>>> eggs = {'name': 'Zophie', 'species': 'cat', 'age': '8'}
>>> list(eggs)
['name', 'species', 'age']
>>> ham = {'species': 'cat', 'age': '8', 'name': 'Zophie'}
>>> list(ham)
['species', 'age', 'name']

Các từ điển vẫn chưa được sắp xếp, vì bạn có thể truy cập các mục trong đó bằng cách sử dụng các chỉ số nguyên như eggs[0] hoặc ham[2]. Bạn không nên dựa vào hành vi này, vì các từ điển trong các phiên bản cũ hơn của Python không nhớ thứ tự chèn của các cặp khóa-giá trị. Ví dụ, chú ý cách danh sách không phù hợp với thứ tự chèn của các cặp từ khóa-giá trị từ điển khi chúng ta chạy mã này trong Python 3.5:

>>> spam = {}
>>> spam['first key'] = 'value'
>>> spam['second key'] = 'value'
>>> spam['third key'] = 'value'
>>> list(spam)
['first key', 'third key', 'second key']

Phương thức keys(), values(), items()
Có ba phương thức từ điển sẽ trả về các giá trị giống như danh sách của các keys(), values() hoặc cả keys và values: keys (), values () và items ().
Các giá trị được trả về bởi các phương thức này không phải đúng là danh sách: chúng không thể được sửa đổi và không có phương thức append (). Nhưng các loại dữ liệu này (dict_keys, dict_values và dict_items, tương ứng) có thể được sử dụng cho các vòng lặp. Để xem các phương thức này hoạt động như thế nào, hãy nhập thông tin sau vào command line:

>>> spam = {'color': 'red', 'age': 42}
>>> for v in spam.values():
... print(v)
red
42

Ở đây, một vòng lặp for lặp lại qua từng giá trị trong từ điển spam. Một vòng lặp for cũng có thể lặp lại các khóa hoặc cả khóa và giá trị:

>>> for k in spam.keys():
... print(k)
color
age
>>> for i in spam.items():
... print(i)
('color', 'red')
('age', 42)

Khi bạn sử dụng các phương thức keys (), values () và items (), một vòng lặp for có thể lặp lại các cặp khóa, giá trị hoặc cặp giá trị khóa trong từ điển, tương ứng.
Lưu ý rằng các giá trị trong giá trị dict_items được trả về bởi phương thức items () là các bộ dữ liệu của khóa và giá trị. Nếu bạn muốn có một danh sách thực sự từ một trong các phương thức này, hãy chuyển giá trị trả về giống như danh sách của nó cho hàm list (). Nhập thông tin sau vào command line:

>>> spam = {'color': 'red', 'age': 42}
>>> spam.keys()
dict_keys(['color', 'age'])
>>> list(spam.keys())
['color', 'age']

Dòng danh sách (spam.keys ()) lấy giá trị dict_keys được trả về từ keys() và chuyển nó vào list(), sau đó trả về giá trị danh sách là [‘color’, ‘age’].
Bạn cũng có thể sử dụng nhiều thủ thuật gán trong một vòng lặp for để gán khóa và giá trị cho các biến riêng biệt. Nhập thông tin sau vào command line:

>>> spam = {'color': 'red', 'age': 42}
>>> for k, v in spam.items():
... print('Key: ' + k + ' Value: ' + str(v))
Key: age Value: 42
Key: color Value: red

Nhớ lại từ chương trước rằng các toán tử trong và không trong toán tử có thể kiểm tra xem một giá trị có tồn tại trong danh sách hay không. Bạn cũng có thể sử dụng các toán tử này để xem liệu một khóa hoặc giá trị nhất định có tồn tại trong từ điển hay không. Nhập thông tin sau vào command line:

>>> spam = {'name': 'Zophie', 'age': 7}
>>> 'name' in spam.keys()
True
>>> 'Zophie' in spam.values()
True
>>> 'color' in spam.keys()
False
>>> 'color' not in spam.keys()
True
>>> 'color' in spam
False

Trong ví dụ trước, lưu ý rằng ‘color’ in spam thực chất là một phiên bản ngắn hơn của cách viết “color” in spam.keys (). Đây luôn là trường hợp: nếu bạn muốn kiểm tra xem một giá trị có phải là (hoặc không là) một khóa trong từ điển hay không, bạn chỉ cần sử dụng từ khóa in (hoặc not in) với chính giá trị từ điển.
Phương thức get()
Nó tẻ nhạt để kiểm tra xem một khóa có tồn tại trong từ điển hay không trước khi truy cập vào giá trị khóa đó. May mắn thay, từ điển có một phương thức get () có hai đối số: khóa của giá trị cần truy xuất và giá trị dự phòng để trả về nếu khóa đó không tồn tại. Nhập thông tin sau vào command line:

>>> picnicItems = {'apples': 5, 'cups': 2}
>>> 'I am bringing ' + str(picnicItems.get('cups', 0)) + ' cups.'
'I am bringing 2 cups.'
>>> 'I am bringing ' + str(picnicItems.get('eggs', 0)) + ' eggs.'
'I am bringing 0 eggs.'

Vì không có khóa ‘eggs’ trong từ điển picnicItems, giá trị mặc định 0 được trả về bằng phương thức get (). Nếu không sử dụng get (), mã sẽ gây ra thông báo lỗi, chẳng hạn như trong ví dụ sau:

>>> picnicItems = {'apples': 5, 'cups': 2}
>>> 'I am bringing ' + str(picnicItems['eggs']) + ' eggs.'
Traceback (most recent call last):
  File "<pyshell#34>", line 1, in <module>
    'I am bringing ' + str(picnicItems['eggs']) + ' eggs.'
KeyError: 'eggs'

Phương thức setdefault()
Bạn thường sẽ phải đặt một giá trị trong từ điển cho một khóa nhất định chỉ khi khóa đó chưa có giá trị. Mã trông giống như thế này

spam = {'name': 'Pooka', 'age': 5}
if 'color' not in spam:
	spam['color'] = 'black'

Phương thức setdefault () cung cấp một cách để làm điều này trong một dòng mã. Đối số đầu tiên được truyền cho phương thức là khóa để kiểm tra và đối số thứ hai là giá trị được đặt ở khóa đó nếu khóa không tồn tại. Nếu khóa tồn tại, phương thức setdefault () trả về giá trị khóa. Nhập thông tin sau vào command line:

>>> spam = {'name': 'Pooka', 'age': 5}
>>> spam.setdefault('color', 'black')
'black'
>>> spam
{'color': 'black', 'age': 5, 'name': 'Pooka'}
>>> spam.setdefault('color', 'white')
'black'
>>> spam
{'color': 'black', 'age': 5, 'name': 'Pooka'}

Lần đầu tiên setdefault () được gọi, từ điển trong spam thay đổi đến {‘color’: ‘black’, ‘age’: 5, ‘name’: ‘Pooka’}. Phương thức trả về giá trị ‘black’ vì đây là giá trị được đặt cho khóa ‘color’. Khi nào
spam.setdefault (‘color’, ‘white’) được gọi tiếp theo, giá trị của khóa đó không được thay đổi thành ‘white’, vì spam đã có khóa có tên là ‘color’. Phương thức setdefault () là một phím tắt đẹp để đảm bảo rằng khóa tồn tại. Đây là một chương trình ngắn đếm số lần xuất hiện của mỗi chữ cái trong một chuỗi. Mở cửa sổ soạn thảo văn bản và nhập mã sau đây, lưu nó dưới dạng characterCount.py:

message = 'It was a bright cold day in April, and the clocks were striking thirteen.'
count = {}
for character in message:
	count.setdefault(character, 0)
	count[character] = count[character] + 1
print(count)

Chương trình lặp trên mỗi ký tự trong chuỗi tin nhắn biến đổi, tính tần suất mỗi ký tự xuất hiện. Cuộc gọi phương thức setdefault () đảm bảo rằng khóa nằm trong từ điển count(với giá trị mặc định là 0) vì vậy chương trình sẽ không ném lỗi KeyError khi count[character] = count[character] + 1 được thực thi. Khi bạn chạy chương trình này, đầu ra sẽ như thế này:
`

{’ ': 13, ‘,’: 1, ‘.’: 1, ‘A’: 1, ‘I’: 1, ‘a’: 4, ‘c’: 3, ‘b’: 1, ‘e’: 5, ‘d’: 3, ‘g’: 2, ‘i’: 6, ‘h’: 3, ‘k’: 2, ‘l’: 3, ‘o’: 2, ‘n’: 4, ‘p’: 1, ‘s’: 3, ‘r’: 5, ‘t’: 6, ‘w’: 2, ‘y’: 1}

`
Từ đầu ra, bạn có thể thấy chữ cái viết thường c xuất hiện 3 lần, ký tự khoảng trắng xuất hiện 13 lần và chữ in hoa A xuất hiện 1 lần. Chương trình này sẽ hoạt động bất kể chuỗi nào nằm trong biến message, ngay cả khi chuỗi dài hàng triệu ký tự!
Người dịch: Hungdh

3 Likes