1. Motivation

Python là một ngôn ngữ hướng đối tượng, nơi mọi giá trị đều là một object, và các biến chỉ đơn thuần là tên dùng để tham chiếu đến object đó. Object là gì? → Là một đối tượng. Ví dụ cây bút sẽ là một Class còn cây bút mình đang cầm trên tay mới là Object. (Giống ví dụ của thầy Thanh) Tham chiếu là sao? Khi ta đặt a = 5 thì có phải là gán giá trị 5 vào a? → Khi viết a = 5, không phải là “đổ số 5 vào trong cái hộp tên là a”, mà đúng hơn là: → Chúng ta đang dán cái nhãn tên là a lên một cục số 5 có sẵn trong bộ nhớ. Nếu viết b = a, vậy là b tạo ra một bản sao của a, hay là b chỉ “dán nhãn” vào cùng một chỗ giống a? → b cùng trỏ vào một ví trị giống a Nếu sau đó ta viết b = 10 thì b sẽ trỏ sang một số mới còn a thì vẫn trỏ vào 5. Vì số là immutable

2. Variable và Address

Tổng quan

Biến (Variable): Trong Python không thực sự là một cái hộp chứa giá trị như trong một số ngôn ngữ khác. Thay vào đó, biến là một tên dùng để tham chiếu đến một object trong bộ nhớ. Ví dụ: Khi bạn viết x = 10, bạn không tạo ra một “hộp” tên x chứa số 10, mà bạn tạo ra object 10 trong bộ nhớ, rồi gán tên x để trỏ đến nó. Địa chỉ (Address): Là vị trí trong bộ nhớ nơi object được lưu trữ. Python cung cấp hàm id() để kiểm tra địa chỉ (hoặc chính xác hơn là “identity”) của object. Khi hai biến có cùng id(), tức là chúng trỏ đến cùng một object. image 36.png

Mutable và Immutable

Trong Python, tất cả mọi thứ đều là object, nhưng không phải object nào cũng cư xử giống nhau khi được gán hoặc thay đổi. Sự khác biệt lớn nhất nằm ở đặc tính mutable và immutable của từng kiểu dữ liệu.

Immutable objects

là các object không thể bị thay đổi tại chỗ (inplace). Một khi được tạo ra, giá trị của chúng không thể chỉnh sửa trực tiếp. Các kiểu dữ liệu phổ biến thuộc nhóm này là:

  • int
  • float
  • str
  • bool
  • tuple “Không thể thay đổi tại chỗ” (inplace) là gì? → Một object immutable thì khi đã tạo ra rồi, mình không thể sửa bên trong nó được nữa. Nếu muốn “thay đổi”, thì Python sẽ tạo ra object mới hoàn toàn, chứ không sửa cái cũ.
x = "hello"
x = x + " world"

Ở đây, "hello" không bị sửa, mà "hello world" là một object mới, rồi x trỏ sang cái mới đó. Vậy khi ta gán **x = 5**, rồi sau đó **x = 6**, thì có phải Python đã thay đổi số 5 thành 6 không? → Không. Vì int là kiểu dữ liệu immutable. Việc Python làm là tạo ra số 6 sau đó x trỏ đến 6.

  • Vậy số **5** có bị xóa không?

    Số 5 không bị xóa liền dù mình không dùng nữa.

    → Vì Python dùng một cơ chế đặc biệt gọi là bộ đếm tham chiếu (reference count) để quản lý bộ nhớ.

    Cụ thể:

    • Mỗi object trong Python (kể cả số 5) đều đi kèm một “đồng hồ đếm” – đó là số lượng biến (hoặc chỗ nào trong chương trình) đang tham chiếu đến nó.
    • Khi viết a = 5, thì object 5 có 1 tham chiếu.
    • Nếu sau đó viết a = 6, thì:
      • Object 5 bị giảm số tham chiếu đi 1.
      • Nếu không còn tham chiếu nào nữa, thì Python biết: “À, cái số 5 này không ai dùng nữa”, vậy nó sẽ xóa khỏi bộ nhớ (giống như gom rác). → Quá trình gom rác này gọi là 🧹 Garbage Collection
      • Nhưng nếu vẫn còn chỗ khác đang dùng số 5, thì nó giữ lại.

    ❗Nhưng riêng với số nhỏ (như 5) thì có ngoại lệ!

    Python có một tối ưu đặc biệt: Small Integer Caching

    Tức là:

    Các số nguyên nhỏ (thường từ -5 đến 256) sẽ luôn được giữ lại trong bộ nhớ để tái sử dụng, dù không ai trỏ đến.

    → Vì vậy, số 5 không bị xóa, vì nó thuộc vùng “luôn giữ lại” để tiết kiệm chi phí tạo mới.

    • Chi phí tạo mới là gì?

      Trong máy tính, mỗi lần mình “tạo mới” một thứ — dù là số, chữ, danh sách hay gì đi nữa — máy tính phải làm một số công việc sau: Vd: tạo một số mới như x = 999999

      1. Xin vùng nhớ (allocate memory)

      Máy tính cần tìm và đặt chỗ trong RAM để lưu trữ con số đó (dù là nhỏ như 5 hay lớn như 999999).

      Giống như khi muốn ghi số điện thoại, mình cần lấy giấy trắng ra trước.

      2. Tạo object Python (object struct)

      Python không lưu số trần trụi. Nó đóng gói số đó thành một object, chứa:

      • Giá trị của số (999999)

      • Loại của nó (int)

      • Số lần được dùng (reference count)

      • Một số cờ và metadata khác

      Giống như viết số lên giấy, rồi gắn thêm nhãn “số nguyên”, “được dùng 1 lần” vào giấy đó.

Tại sao **tuple** là immutable mà vẫn chứa được list là mutable?