Dict và Tệp Python

Bảng mã hoá hàm băm

Cấu trúc bảng băm khoá/giá trị hiệu quả của Python được gọi là "dict". Nội dung của một lệnh có thể được viết dưới dạng một chuỗi các cặp key:value trong các dấu ngoặc nhọn { }, ví dụ: dict = {key1:value1, key2:value2, ... }. Các "Empty dict" (chính tắc trống) chỉ là một cặp dấu ngoặc nhọn {}.

Việc tra cứu hoặc thiết lập một giá trị trong một lệnh chính tả sử dụng dấu ngoặc vuông, ví dụ: dict['foo'] sẽ tra cứu giá trị trong khoá 'foo'. Chuỗi, số và bộ dữ liệu hoạt động dưới dạng khoá và bất kỳ kiểu nào cũng có thể là giá trị. Các loại khác có thể hoạt động chính xác hoặc không hoạt động chính xác dưới dạng các phím (chuỗi và bộ dữ liệu hoạt động trơn tru vì chúng không thể thay đổi). Việc tra cứu một giá trị không có trong lệnh sẽ gửi ra KeyError – sử dụng "in" để kiểm tra xem khoá có nằm trong lệnh hoặc sử dụng dict.get(key) để trả về giá trị hoặc Không có nếu khoá không có (hoặc get(key, not-found) cho phép bạn chỉ định giá trị cần trả về trong trường hợp không tìm thấy).

  ## Can build up a dict by starting with the empty dict {}
  ## and storing key/value pairs into the dict like this:
  ## dict[key] = value-for-that-key
  dict = {}
  dict['a'] = 'alpha'
  dict['g'] = 'gamma'
  dict['o'] = 'omega'

  print(dict) ## {'a': 'alpha', 'o': 'omega', 'g': 'gamma'}

  print(dict['a'])     ## Simple lookup, returns 'alpha'
  dict['a'] = 6       ## Put new key/value into dict
  'a' in dict         ## True
  ## print(dict['z'])                  ## Throws KeyError
  if 'z' in dict: print(dict['z'])     ## Avoid KeyError
  print(dict.get('z'))  ## None (instead of KeyError)

nhập bằng các phím 'a' 'o' 'g'

Theo mặc định, vòng lặp for trên từ điển sẽ lặp lại các khoá của nó. Các khoá sẽ xuất hiện theo thứ tự tuỳ ý. Các phương thức dict.keys() và dict.values() trả về danh sách khoá hoặc giá trị một cách rõ ràng. Ngoài ra còn có items() trả về danh sách các bộ giá trị (khoá, giá trị). Đây là cách hiệu quả nhất để kiểm tra tất cả dữ liệu khoá-giá trị trong từ điển. Tất cả các danh sách này đều có thể được truyền đến hàm sort().

  ## By default, iterating over a dict iterates over its keys.
  ## Note that the keys are in a random order.
  for key in dict:
    print(key)
  ## prints a g o

  ## Exactly the same as above
  for key in dict.keys():
    print(key)

  ## Get the .keys() list:
  print(dict.keys())  ## dict_keys(['a', 'o', 'g'])

  ## Likewise, there's a .values() list of values
  print(dict.values())  ## dict_values(['alpha', 'omega', 'gamma'])

  ## Common case -- loop over the keys in sorted order,
  ## accessing each key/value
  for key in sorted(dict.keys()):
    print(key, dict[key])

  ## .items() is the dict expressed as (key, value) tuples
  print(dict.items())  ##  dict_items([('a', 'alpha'), ('o', 'omega'), ('g', 'gamma')])

  ## This loop syntax accesses the whole dict by looping
  ## over the .items() tuple list, accessing one (key, value)
  ## pair on each iteration.
  for k, v in dict.items(): print(k, '>', v)
  ## a > alpha    o > omega     g > gamma

Lưu ý về chiến lược: từ quan điểm hiệu suất, từ điển là một trong những công cụ tuyệt vời nhất và bạn nên sử dụng từ điển ở những nơi có thể như một cách dễ dàng để sắp xếp dữ liệu. Ví dụ: bạn có thể đọc tệp nhật ký trong đó mỗi dòng bắt đầu bằng một địa chỉ IP, sau đó lưu trữ dữ liệu vào một bản ghi chính tả bằng cách sử dụng địa chỉ IP làm khoá và danh sách dòng mà trong đó dữ liệu xuất hiện dưới dạng giá trị. Sau khi đã đọc toàn bộ tệp, bạn có thể tra cứu bất kỳ địa chỉ IP nào và xem ngay danh sách các dòng của địa chỉ IP đó. Từ điển tiếp nhận dữ liệu phân tán và làm cho dữ liệu nhất quán.

Định dạng nhập bằng giọng nói

Toán tử % hoạt động thuận tiện để thay thế các giá trị từ một lệnh thành một chuỗi theo tên:

  h = {}
  h['word'] = 'garfield'
  h['count'] = 42
  s = 'I want %(count)d copies of %(word)s' % h  # %d for int, %s for string
  # 'I want 42 copies of garfield'

  # You can also use str.format().
  s = 'I want {count:d} copies of {word}'.format(h)

Del

Toán tử "del" sẽ xoá. Trong trường hợp đơn giản nhất, công cụ này có thể xoá định nghĩa của một biến, như thể biến đó chưa được xác định. Bạn cũng có thể sử dụng Del trên các phần tử hoặc lát cắt của danh sách để xoá phần đó của danh sách và để xoá các mục nhập khỏi từ điển.

  var = 6
  del var  # var no more!

  list = ['a', 'b', 'c', 'd']
  del list[0]     ## Delete first element
  del list[-2:]   ## Delete last two elements
  print(list)      ## ['b']

  dict = {'a':1, 'b':2, 'c':3}
  del dict['b']   ## Delete 'b' entry
  print(dict)      ## {'a':1, 'c':3}

Files

Hàm open() mở và trả về tên người dùng tệp có thể được dùng để đọc hoặc ghi tệp theo cách thông thường. Mã f = open('name', 'r') mở tệp vào biến f, sẵn sàng cho các thao tác đọc và sử dụng f.close() khi hoàn tất. Thay vì "r", hãy dùng "w" để viết và "a" để nối kết quả. Tiêu chuẩn for-loop hoạt động với tệp văn bản, lặp lại qua các dòng của tệp (phương thức này chỉ áp dụng cho tệp văn bản, không áp dụng cho tệp nhị phân). Kỹ thuật vòng lặp for là một cách đơn giản và hiệu quả để xem tất cả các dòng trong một tệp văn bản:

  # Echo the contents of a text file
  f = open('foo.txt', 'rt', encoding='utf-8')
  for line in f:   ## iterates over the lines of the file
    print(line, end='')    ## end='' so print does not add an end-of-line char
                           ## since 'line' already includes the end-of-line.
  f.close()

Đọc từng dòng một có chất lượng tuyệt vời mà không phải tất cả tệp đều cần vừa với bộ nhớ cùng một lúc – tiện dụng nếu bạn muốn xem mọi dòng trong tệp 10 gigabyte mà không cần sử dụng bộ nhớ 10 gigabyte. Phương thức f.readlines() đọc toàn bộ tệp vào bộ nhớ và trả về nội dung của tệp dưới dạng danh sách các dòng. Phương thức f.read() đọc toàn bộ tệp thành một chuỗi duy nhất. Đây có thể là một cách thuận tiện để xử lý tất cả văn bản cùng một lúc, chẳng hạn như với các biểu thức chính quy mà chúng ta sẽ thấy sau.

Để ghi, phương thức f.write(string) là cách dễ nhất để ghi dữ liệu vào tệp đầu ra mở. Hoặc bạn có thể sử dụng "print" với một tệp đang mở như "print(string, file=f)".

Tệp Unicode

Để đọc và ghi các tệp được mã hoá unicode, hãy sử dụng chế độ "không" và chỉ định rõ một phương thức mã hoá:


with open('foo.txt', 'rt', encoding='utf-8') as f:
  for line in f:
    # here line is a *unicode* string

with open('write_test', encoding='utf-8', mode='wt') as f:
    f.write('\u20ACunicode\u20AC\n') #  €unicode€
    # AKA print('\u20ACunicode\u20AC', file=f)  ## which auto-adds end='\n'

Phát triển dần việc tập thể dục

Khi tạo chương trình Python, đừng viết mọi thứ chỉ trong một bước. Thay vào đó, chỉ xác định mốc quan trọng đầu tiên, ví dụ: "bước đầu tiên là trích xuất danh sách các từ". Viết mã để đạt được cột mốc đó và chỉ in cấu trúc dữ liệu của bạn tại thời điểm đó, sau đó bạn có thể thực hiện sys.exit(0) để chương trình không chạy tiếp vào những phần chưa hoàn tất. Khi mã mốc quan trọng đã hoạt động, bạn có thể viết mã cho mốc quan trọng tiếp theo. Việc có thể xem bản in các biến ở một trạng thái có thể giúp bạn suy nghĩ về cách biến đổi các biến đó để chuyển sang trạng thái tiếp theo. Python hoạt động rất nhanh với mẫu này, cho phép bạn thực hiện một chút thay đổi và chạy chương trình để xem cách thức hoạt động của chương trình. Hãy tận dụng quy trình quay vòng nhanh chóng này để xây dựng chương trình của bạn chỉ trong vài bước.

Bài tập: wordcount.py

Kết hợp tất cả tài liệu cơ bản về Python – chuỗi, danh sách, bản ghi chính tả, bộ đối tượng, tệp – hãy thử làm bài tập tóm tắt wordcount.py trong Bài tập cơ bản.