Chương 8: Danh sách (Lists)

Rồi, chúng ta sẽ bắt đầu Chương 8: Danh sách (Lists) theo cấu trúc hướng dẫn toàn diện nhất (phiên bản 8.0).


1. Tóm Lược Nội Dung Chính

Chương 8 giới thiệu một trong những kiểu dữ liệu mạnh mẽ và hữu ích nhất của Python: danh sách (list). Danh sách cho phép bạn lưu trữ một tập hợp các giá trị (thuộc bất kỳ kiểu nào) trong một biến duy nhất. Khác với chuỗi, danh sách là khả biến (mutable), nghĩa là bạn có thể thay đổi nội dung của nó. Bạn sẽ học cách tạo, truy cập, cắt lát, và sử dụng các phương thức để thao tác với danh sách, một kỹ năng cốt lõi để xử lý các bộ dữ liệu.


2. Phân Tích Toàn Diện Từng Mục (Section-by-Section)

Mục 8.1: Danh sách là một chuỗi tuần tự (A list is a sequence)

  • a. Giải thích & Ví dụ Code:

    • Giải thích: Giống như chuỗi, danh sách cũng là một chuỗi tuần tự các giá trị (được gọi là các phần tử - elements). Điều này có nghĩa là bạn có thể truy cập các phần tử bằng chỉ số (bắt đầu từ 0) và dùng vòng lặp for để duyệt qua chúng.

    • Ví dụ Code:

      Python

      # Một danh sách các chuỗi và một danh sách các số
      cheeses = ['Cheddar', 'Edam', 'Gouda']
      numbers = [42, 123]
      
      # Truy cập phần tử đầu tiên của danh sách cheeses
      print(cheeses[0])
      

      Kết quả đầu ra (Output): Cheddar

  • b. Thực hành & Kiểm tra:

    • Thực hành nhỏ : Với danh sách numbers ở trên, làm thế nào để bạn lấy ra số 123?

    • => Lời giải: numbers[1]

Mục 8.2: Danh sách là khả biến (Lists are mutable)

  • a. Giải thích & Ví dụ Code:

    • Giải thích: Đây là điểm khác biệt lớn nhất so với chuỗi. "Khả biến" có nghĩa là bạn có thể thay đổi nội dung của danh sách sau khi đã tạo ra nó bằng cách gán giá trị mới cho một chỉ số cụ thể.

    • Ví dụ Code:

      Python

      numbers = [42, 123]
      print('Trước khi thay đổi:', numbers)
      
      # Thay đổi phần tử thứ hai (chỉ số 1)
      numbers[1] = 5
      print('Sau khi thay đổi:', numbers)
      

      Kết quả đầu ra (Output):

      Trước khi thay đổi: [42, 123]
      Sau khi thay đổi: [42, 5]
      
  • b. Thực hành & Kiểm tra:

    • Thực hành nhỏ : Toán tử in có hoạt động trên danh sách không?

    • => Lời giải: Có. 'Edam' in cheeses sẽ trả về True.

Mục 8.3 & 8.4: Lặp qua danh sách & Các phép toán

  • a. Giải thích & Ví dụ Code:

    • Giải thích: Cách phổ biến nhất để duyệt qua các phần tử của danh sách là dùng vòng lặp for. Giống như chuỗi, toán tử + dùng để nối hai danh sách và * dùng để lặp lại một danh sách.

    • Ví dụ Code:

      Python

      # Lặp qua danh sách
      for cheese in ['Cheddar', 'Edam', 'Gouda']:
          print(cheese)
      
      # Các phép toán
      a = [1, 2, 3]
      b = [4, 5, 6]
      c = a + b
      print(c) # Output: [1, 2, 3, 4, 5, 6]
      print([0] * 4) # Output: [0, 0, 0, 0]
      
  • b. Thực hành & Kiểm tra:

    • Thực hành nhỏ : [1, 2] + [3, 4][1, 2] * 2 sẽ cho ra kết quả gì?

    • => Lời giải: [1, 2, 3, 4][1, 2, 1, 2].

Mục 8.5 & 8.6: Cắt lát & Phương thức danh sách

  • a. Giải thích & Ví dụ Code:

    • Giải thích: Cắt lát (slicing) trên danh sách hoạt động y hệt như trên chuỗi. Phương thức (method) là các hàm gắn liền với đối tượng danh sách. Một số phương thức quan trọng là append (thêm một phần tử vào cuối) và sort (sắp xếp danh sách).

    • Ví dụ Code:

      Python

      t = ['a', 'b', 'c', 'd', 'e', 'f']
      print(t[1:3]) # Cắt lát. Output: ['b', 'c']
      
      t.append('g') # Dùng phương thức append
      print(t) # Output: ['a', 'b', 'c', 'd', 'e', 'f', 'g']
      
      t.sort(reverse=True) # Sắp xếp ngược
      print(t) # Output: ['g', 'f', 'e', 'd', 'c', 'b', 'a']
      
  • b. Thực hành & Kiểm tra:

    • Thực hành nhỏ : Bạn có một danh sách nums = [3, 1]. Làm thế nào để thêm số 2 vào cuối danh sách?

    • => Lời giải: nums.append(2)

Mục 8.7: Xóa phần tử

  • a. Giải thích & Ví dụ Code:

    • Giải thích: Có nhiều cách để xóa phần tử:

      • pop(index): Xóa phần tử tại index và trả về giá trị đã xóa. Nếu không có index, nó xóa và trả về phần tử cuối cùng.

      • remove(value): Tìm và xóa phần tử đầu tiên có giá trị là value.

      • del list[index]: Một câu lệnh (không phải phương thức) để xóa phần tử tại index.

    • Ví dụ Code:

      Python

      t = ['a', 'b', 'c']
      x = t.pop(1) # Xóa 'b' và gán cho x
      print(t) # Output: ['a', 'c']
      print(x) # Output: b
      
      t2 = ['a', 'b', 'c', 'b']
      t2.remove('b') # Xóa chữ 'b' đầu tiên
      print(t2) # Output: ['a', 'c', 'b']
      
  • b. Thực hành & Kiểm tra:

    • Thực hành nhỏ : Bạn muốn xóa phần tử thứ hai khỏi danh sách letters = ['x', 'y', 'z'] mà không cần biết giá trị của nó. Bạn sẽ dùng pop, remove, hay del?

    • => Lời giải: Dùng letters.pop(1) hoặc del letters[1].

Mục 8.8 & 8.9: Danh sách và hàm / Danh sách và chuỗi

  • a. Giải thích & Ví dụ Code:

    • Giải thích: Các hàm có sẵn như len, max, min, sum hoạt động rất tốt trên danh sách các số. Mối quan hệ giữa danh sách và chuỗi rất quan trọng: phương thức chuỗi .split() có thể tách một chuỗi thành một danh sách các từ, và phương thức danh sách .join() có thể làm điều ngược lại.

    • Ví dụ Code:

      Python

      s = 'spam-spam-spam'
      delimiter = '-'
      words = s.split(delimiter) # Tách chuỗi
      print(words) # Output: ['spam', 'spam', 'spam']
      
      t = ['pining', 'for', 'the', 'fjords']
      delimiter = ' '
      sentence = delimiter.join(t) # Nối danh sách
      print(sentence) # Output: pining for the fjords
      
  • b. Thực hành & Kiểm tra:

    • Thực hành nhỏ : line = 'Hello world'. line.split() sẽ trả về gì?

    • => Lời giải: ['Hello', 'world']. (Mặc định split() sẽ tách theo khoảng trắng).

Mục 8.10 & 8.11: Phân tích dòng / Đối tượng và giá trị

  • a. Giải thích & Ví dụ Code:

    • Giải thích: Ta có thể kết hợp split với kiến thức về chỉ số để phân tích và trích xuất thông tin từ các dòng dữ liệu. Một khái niệm quan trọng là tham chiếu (aliasing): khi bạn gán b = a với a là một danh sách, cả ab đều cùng trỏ đến một đối tượng danh sách trong bộ nhớ. Thay đổi b cũng sẽ làm thay đổi a.

    • Ví dụ Code:

      Python

      a = [1, 2, 3]
      b = a # b bây giờ là một tên khác của a
      b[0] = 99
      print(a) # a cũng bị thay đổi!
      

      Kết quả đầu ra (Output): [99, 2, 3]

  • b. Thực hành & Kiểm tra:

    • Thực hành nhỏ : Làm thế nào để tạo một bản sao (clone) của danh sách a để thay đổi bản sao không ảnh hưởng đến bản gốc?

    • => Lời giải: Dùng kỹ thuật cắt lát: b = a[:].

Mục 8.12: Tham số danh sách

  • a. Giải thích & Ví dụ Code:

    • Giải thích: Khi bạn truyền một danh sách làm đối số cho một hàm, hàm đó sẽ nhận được một tham chiếu đến danh sách gốc. Do đó, nếu hàm đó thay đổi danh sách, sự thay đổi đó sẽ có hiệu lực cả ở bên ngoài hàm.

    • Ví dụ Code:

      Python

      def delete_head(t):
          del t[0]
      
      letters = ['a', 'b', 'c']
      delete_head(letters) # Hàm này thay đổi danh sách gốc
      print(letters)
      

      Kết quả đầu ra (Output): ['b', 'c']

  • b. Thực hành & Kiểm tra:

    • Thực hành nhỏ : Tại sao hành vi này khác với các biến số và chuỗi khi truyền vào hàm?

    • => Lời giải: Vì số và chuỗi là bất biến (immutable), còn danh sách là khả biến (mutable).


3. Tổng Kết Chương & Thử Thách

  • a. Kiến thức cốt lõi:

    • Lỗi thường gặp: Cố gắng sửa đổi danh sách trong khi đang lặp qua nó có thể gây ra lỗi khó lường. Gán giá trị cho một phương thức (my_list = my_list.sort()) sẽ làm my_list trở thành None, vì các phương thức như sort sửa đổi danh sách tại chỗ và trả về None.

    • Điểm cần tập trung: Khái niệm tính khả biến (mutability) là quan trọng nhất. Hãy hiểu rõ sự khác biệt giữa việc thay đổi một đối tượng tại chỗ và việc tạo ra một đối tượng mới.

    • Lưu ý "Pythonic": Dùng phương thức split() để phân tích các chuỗi có cấu trúc là một kỹ thuật cực kỳ phổ biến và hiệu quả.

  • b. Bài Tập Coding Cuối Chương 💻: Viết một chương trình thực hiện các việc sau:

    1. Mở file romeo.txt (bạn có thể tải file này từ trang web của sách, hoặc tạo một file văn bản tương tự).

    2. Đọc file theo từng dòng.

    3. Với mỗi dòng, tách nó thành một danh sách các từ.

    4. Xây dựng một danh sách chứa tất cả các từ duy nhất (mỗi từ chỉ xuất hiện một lần) từ toàn bộ file.

    5. Sau khi xử lý xong toàn bộ file, hãy sắp xếp danh sách các từ duy nhất theo thứ tự bảng chữ cái và in chúng ra.