Python - Tham Chiếu Yếu

Xin chào, các bạn nhà lập trình nhảm nhiên! Hôm nay, chúng ta sẽ bơi lội vào thế giới thú vị của các tham chiếu yếu trong Python. Đừng lo nếu bạn mới bắt đầu học lập trình – tôi sẽ hướng dẫn bạn qua khái niệm này bước từng bước, đúng như tôi đã làm cho hàng ngàn học viên trong những năm dạy học. Hãy cùng nhau bắt đầu hành trình thú vị này!

Python - Weak References

Tham Chiếu Yếu Là Gì?

Trước khi bước vào chi tiết, hãy hiểu rõ về các tham chiếu yếu. Hãy tưởng tượng bạn đang ở một buổi tiệc và gặp một người mới. Bạn có thể nhớ đến khuôn mặt của họ, nhưng không nhất thiết phải nhớ tên của họ. Đó chơi như một tham chiếu yếu trong Python!

Trong lingo lập trình, một tham chiếu yếu cho phép bạn tham chiếu đến một đối tượng mà không tăng số lượng tham chiếu của nó. Điều này có nghĩa là đối tượng có thể bị thu hồi bộ nhớ (được làm sạch bởi Python) ngay cả khi vẫn còn các tham chiếu yếu chỉ đến nó.

Hãy xem một ví dụ đơn giản:

import weakref

class Party:
def __init__(self, name):
self.name = name

# Tạo một đối tượng Party
awesome_party = Party("Python Programmers' Bash")

# Tạo một tham chiếu yếu đến buổi tiệc
weak_party = weakref.ref(awesome_party)

# Truy cập đối tượng qua tham chiếu yếu
print(weak_party().name)  # Output: Python Programmers' Bash

# Xóa đối tượng gốc
del awesome_party

# Thử truy cập đối tượng một lần nữa
print(weak_party())  # Output: None

Trong ví dụ này, chúng ta tạo một đối tượng Party và một tham chiếu yếu đến nó. Chúng ta có thể truy cập đối tượng qua tham chiếu yếu, nhưng khi xóa đối tượng gốc, tham chiếu yếu trả về None.

Hàm Gọi Lại (Callback Function)

Bây giờ, hãy thêm một chút phấn chấn vào các tham chiếu yếu của chúng ta với các hàm gọi lại. Những hàm này như những người助手 nhỏ nhắn nhủ vào hành động khi một đối tượng sắp được thu hồi bộ nhớ.

import weakref

def party_over(reference):
print("Buổi tiệc đã kết thúc! Thời gian để dọn dẹp.")

class Party:
def __init__(self, name):
self.name = name

awesome_party = Party("Python Coders' Fiesta")
weak_party = weakref.ref(awesome_party, party_over)

del awesome_party
# Output: Buổi tiệc đã kết thúc! Thời gian để dọn dẹp.

Ở đây, hàm party_over được gọi khi đối tượng awesome_party sắp được thu hồi bộ nhớ. Nó như có một người bạn trách nhiệm nhắc nhở bạn dọn dẹp sau buổi tiệc!

Đối Tượng Cuối Cùng (Finalizing Objects)

Đôi khi, chúng ta muốn thực hiện một số hành động ngay trước khi một đối tượng bị thu hồi bộ nhớ. Đây là nơi các đối tượng cuối cùng có thể sử dụng được. Chúng giống như lời chào lần cuối của một đối tượng trước khi nó rời xa.

import weakref

class Party:
def __init__(self, name):
self.name = name

def __del__(self):
print(f"Dọn dẹp sau {self.name}")

awesome_party = Party("Python Picnic")
weak_party = weakref.ref(awesome_party)

del awesome_party
# Output: Dọn dẹp sau Python Picnic

Trong ví dụ này, phương thức __del__ hoạt động như một đối tượng cuối cùng, in ra thông báo khi đối tượng sắp bị thu hồi bộ nhớ.

WeakKeyDictionary

Bây giờ, hãy nói về một loại từ điển đặc biệt – WeakKeyDictionary. Nó giống như một từ điển bình thường, nhưng có một chút lạ: các khóa là các tham chiếu yếu!

import weakref

class Attendee:
def __init__(self, name):
self.name = name

party_roles = weakref.WeakKeyDictionary()

alice = Attendee("Alice")
bob = Attendee("Bob")

party_roles[alice] = "DJ"
party_roles[bob] = "Dancer"

print(party_roles[alice])  # Output: DJ
print(party_roles[bob])    # Output: Dancer

del alice
print(list(party_roles.keys()))  # Output: [<__main__.Attendee object at ...>]

Trong ví dụ này, khi chúng ta xóa alice, mục của cô ấy trong từ điển party_roles sẽ bị xóa tự động. Có như cô ấy đã rời khỏi buổi tiệc mà không báo cáo bất kỳ ai!

WeakValueDictionary

Cuối cùng nhưng không kém phần quan trọng, hãy gặp WeakValueDictionary. Lần này, là các giá trị là các tham chiếu yếu, không phải là các khóa.

import weakref

class Party:
def __init__(self, name):
self.name = name

scheduled_parties = weakref.WeakValueDictionary()

summer_bash = Party("Summer Bash")
winter_gala = Party("Winter Gala")

scheduled_parties["June"] = summer_bash
scheduled_parties["December"] = winter_gala

print(scheduled_parties["June"].name)  # Output: Summer Bash

del summer_bash
print(list(scheduled_parties.keys()))  # Output: ['December']

Ở đây, khi chúng ta xóa summer_bash, mục của nó trong từ điển scheduled_parties sẽ biến mất tự động. Có như buổi tiệc đã bị hủy mà không ai cập nhật lịch trình!

Kết Luận

Và thế là xong, các bạn! Chúng ta đã hành trình qua thế giới các tham chiếu yếu trong Python. Từ các tham chiếu yếu cơ bản đến các hàm gọi lại, các đối tượng cuối cùng và các từ điển yếu, bạn đã có một nền tảng vững chắc trong khái niệm mạnh mẽ này.

Nhớ rằng, các tham chiếu yếu như những khách buổi tiệc lịch sự – họ không ở quá lâu và biết khi nào là thời gian để rời đi. Chúng rất hữu ích cho việc quản lý bộ nhớ hiệu quả và tránh các tham chiếu vòng tròn.

Khi bạn tiếp tục hành trình Python của mình, hãy giữ các khái niệm này trong tâm. Chúng có thể xuất hiện khi bạn không mong đợi!

Method/Class Mô Tả
weakref.ref() Tạo một tham chiếu yếu đến một đối tượng
weakref.proxy() Tạo một proxy cho tham chiếu yếu
weakref.getweakrefcount() Trả về số lượng tham chiếu yếu đến một đối tượng
weakref.getweakrefs() Trả về danh sách tất cả các tham chiếu yếu đến một đối tượng
weakref.WeakKeyDictionary() Tạo một từ điển với các tham chiếu yếu làm khóa
weakref.WeakValueDictionary() Tạo một từ điển với các tham chiếu yếu làm giá trị
weakref.finalize() Đăng ký một hàm cuối cùng được gọi khi một đối tượng bị thu hồi bộ nhớ

Chúc các bạn mãi mãi có những khám phá thú vị trong hành trình lập trình Python của mình!

Credits: Image by storyset