Cách sử dụng Closure trong Python

Ở bài viết này, chúng ta sẽ cùng bạn tìm hiểu về Closure trong Python, làm thế nào để xác định một Closure và lý do tại sao bạn nên sử dụng nó. Hãy cùng đi tìm lời giải đáp!

Biến nonlocal trong hàm lồng nhau

Trước khi đi vào tìm hiểu Closure là gì, hãy lướt qua hàm lồng nhau và biến nonlocal một chút.

Một hàm được định nghĩa bên trong một hàm khác được gọi là hàm lồng nhau. Các hàm lồng nhau có thể truy cập các biến và trả về kết quả của các hàm trong phạm vi kèm theo.

Trong Python, biến nonlocal được sử dụng trong hàm lồng nhau nơi mà phạm vi cục bộ không được định nghĩa. Nói dễ hiểu thì biến nonlocal không phải biến local, không phải biến global, bạn khai báo một biến là nonlocal khi muốn sử dụng nó ở phạm vi rộng hơn local, nhưng chưa đến mức global.

Ví dụ: Hàm lồng nhau truy cập biến nonlocal

def print_msg(msg):
# Hàm bên ngoài

    def printer():
# Hàm lồng nhau
        print(msg)

    printer()

# Chạy hàm
# Output: Hello
print_msg("Hello")

Ta có thể thấy rằng, hàm lồng nhau printer() có thể truy cập vào biến nonlocal msg của hàm bên ngoài nó.

Định nghĩa hàm Closure trong Python

Closure thường được tạo ra bởi hàm lồng nhau, có thể hiểu là những hàm ghi nhớ không gian nơi mà nó tạo ra.

def print_msg(msg):
# Hàm bê ngoài

    def printer():
# Hàm lồng nhau
        print(msg)

    return printer

another = print_msg("Hello")
another()

Trong ví dụ trên, khi print_msg được gọi với chuỗi “Hello”, hàm con printer sẽ được định nghĩa cùng với giá trị của msg cục bộ. Sau đó, hàm another() được gọi. Khi chúng ta thực thi hàm, bởi vì printer tham chiếu đến msg nên giá trị này sẽ được ghi nhớ ngay cả khi hàm print_msg đã kết thúc từ trước.

Chạy chúng trong Python shell để xem output:

>>> del print_msg
>>> another()
Hello
>>> print_msg("Hello")
Traceback (most recent call last):
...
NameError: name 'print_msg' is not defined

Cần chú ý rằng, closure được tạo ra bởi hàm lồng nhau nhưng không phải hàm lồng nhau nào cũng là closure. Closure chỉ được tạo ra khi hàm con truy cập đến những biến cục bộ trong scope được đóng bởi hàm cha.

Điều kiện để có Closure

Như ở ví dụ trên, ta thấy Closure sử dụng trong Python khi một hàm lồng nhau tham chiếu đến một giá trị trong phạm vi scope, nơi nó được định nghĩa.

Các tiêu chí để tạo Closure trong Python phải được đáp ứng được tóm tắt trong các điểm sau.

Để tạo closure trong Python, các tiêu chí cần phải đáp ứng bao gồm:

  • Có một hàm lồng nhau (hàm được định nghĩa bên trong một hàm khác).
  • Hàm lồng nhau phải tham chiếu đến một giá trị được xác định trong hàm kèm theo.
  • Hàm kèm theo phải trả kết quả về hàm lồng nhau.

Khi nào nên sử dụng Closure?

Closure có thể sử dụng các giá trị global và cung cấp một số dạng dữ liệu ẩn. Closure cũng có thể cung cấp các giải pháp, tạo ra các hàm có nhiều tính chất của lập trình hướng đối tượng để giải quyết vấn đề.

Khi cần định nghĩa một class chỉ với vài phương thức, closure có thể được sử dụng như một giải pháp thay thế nhẹ nhàng hơn lập trình hướng đối tượng. Tuy nhiên là khi các thuộc tính và phương thức nhiều lên, sử dụng lập trình hướng đối tượng sẽ là giải pháp tốt hơn.

Dưới đây là một ví dụ đơn giản trong đó việc đóng có thể thích hợp hơn là xác định một lớp và tạo các đối tượng. Nhưng sở thích là tất cả của bạn.

Ví dụ dưới đây sẽ cho bạn thấy việc sử dụng closure thích hợp hơn phương pháp lập trình hướng đối tượng với việc xác định lớp và tạo các đối tượng. Tuy nhiên, tùy theo cách bạn muốn, dùng cái nào cũng được nhé.

def make_multiplier_of(n):
    def multiplier(x):
        return x * n
    return multiplier

# He so 3
times3 = make_multiplier_of(3)

# He so 5
times5 = make_multiplier_of(5)

# Output: 27
print(times3(9))

# Output: 15
print(times5(3))

# Output: 30
print(times5(times3(2)))

Trong những ứng dụng của hàm lồng nhau, closure chính là ứng dụng quan trọng nhất. Nếu biết sử dụng nó đúng cách, chúng ta sẽ viết được những đoạn code đẹp, hiệu suất cao và dễ bảo trì.

Leave a Reply