Closure

Python SELF VI
Mức độ , Bài học
Có sẵn

3.1 Giới thiệu về closures

Closure là một hàm bắt giữ các biến từ phạm vi bao quanh nó, ngay cả sau khi phạm vi đó đã hoàn tất thực thi. Điều này có nghĩa là closure có thể "nhớ" các giá trị biến từ phạm vi bên ngoài của nó và tiếp tục làm việc với chúng, ngay cả khi phạm vi đó không còn hoạt động nữa.

Để hiểu cách hoạt động của closures, hãy xem ví dụ sau:


def outer_function(x):
    def inner_function(y):
        return x + y

    return inner_function
    
closure = outer_function(10)
print(closure(5))  # Kết quả: 15

Hãy cùng nhau phân tích đoạn mã trên:

Hàm bên ngoài (outer_function): Hàm này nhận đối số x và định nghĩa một hàm bên trong inner_function, nhận đối số y và trả về tổng của xy. Hàm inner_function không được gọi bên trong outer_function, chỉ được khai báo thôi.

Hàm bên trong (inner_function): Hàm này được trả về từ outer_function và giữ một tham chiếu tới giá trị của x, đã được truyền vào outer_function.

Closure: Biến closure trở thành closure, "nhớ" giá trị x (trong trường hợp này là 10) và có thể sử dụng nó khi được gọi.

Thường thì không ai có thể dùng closures một cách thuần thục ngay lần đầu. Vì vậy, hãy cùng thử nâng cao sự hiểu biết của bạn về các closures qua các ví dụ nhé.

3.2 Ví dụ về việc sử dụng closures

Tạo hàm generator

Closures có thể được sử dụng để tạo các hàm generator, tạo ra các dãy giá trị.


def make_counter():
    count = 0

    def counter():
        nonlocal count
        count += 1
        return count

    return counter
    
counter = make_counter()
print(counter())  # Kết quả: 1
print(counter())  # Kết quả: 2
print(counter())  # Kết quả: 3

Giải thích:

Hàm generator (make_counter): Hàm này tạo một biến count và trả về một hàm bên trong counter, hàm này tăng giá trị của count và trả về nó.

Closure: Hàm counter lưu trữ trạng thái của biến count và có thể thay đổi nó mỗi khi được gọi.

Tạo hàm với cấu hình

Closures có thể được sử dụng để tạo ra các hàm với cấu hình được xác định từ trước.


def make_multiplier(factor):
    def multiplier(x):
        return x * factor

    return multiplier
    
double = make_multiplier(2)
triple = make_multiplier(3)
    
print(double(5))  # Kết quả: 10
print(triple(5))  # Kết quả: 15

Giải thích:

Hàm cấu hình (make_multiplier): Hàm này nhận một hệ số factor và trả về một hàm nội bộ multiplier, hàm này nhân giá trị đầu vào với factor.

Closures: Các hàm doubletriple là closures, chúng lưu trữ các giá trị factor riêng của mình và sử dụng chúng để nhân.

Lọc dữ liệu với tham số

Closures có thể rất hữu ích để tạo ra các hàm lọc với tham số.


def make_filter(threshold):
    def filter_func(value):
        return value > threshold
        
    return filter_func
    
filter_above_10 = make_filter(10)
data = [5, 10, 15, 20]
filtered_data = list(filter(filter_above_10, data))
print(filtered_data)  # Kết quả: [15, 20]

Giải thích:

Hàm lọc (make_filter): Hàm này nhận một giá trị ngưỡng threshold và trả về một hàm nội bộ filter_func, hàm này kiểm tra xem giá trị có lớn hơn ngưỡng không.

Closure: Hàm filter_func lưu trữ giá trị threshold và sử dụng nó để lọc dữ liệu.

3.3 Ưu và nhược điểm của closures

Ưu điểm của việc dùng closures

Đóng gói trạng thái: Closures cho phép đóng gói trạng thái trong hàm, tránh việc dùng biến toàn cục và cải thiện tính dễ đọc và khả năng bảo trì của mã.

Linh hoạt: Closures có thể được sử dụng để tạo ra các hàm với cấu hình hoặc hành vi nhất định, làm cho mã linh hoạt và thích ứng hơn.

Lập trình hàm: Closures là một khái niệm quan trọng trong lập trình hàm, cho phép tạo ra các hàm bậc cao và các cấu trúc hàm khác.

Hạn chế và vấn đề tiềm ẩn

Mặc dù có nhiều ưu điểm, closures cũng có những hạn chế riêng:

Sử dụng bộ nhớ: Closures có thể giữ các tham chiếu tới các đối tượng không còn được sử dụng, điều này có thể dẫn đến rò rỉ bộ nhớ.

Độ khó trong debug: Closures có thể làm phức tạp việc debug mã, vì trạng thái của các biến có thể không rõ ràng.

Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION