39. Đóng cửa và ô

Các bao đóng cho phép hàm lồng nhau sử dụng các biến từ hàm kèm theo sau khi hàm kèm theo đó trả về.```python def make_adder(n): def add(x): return x + n return add

add10 = make_adder(10) print(add10(5)) Đầu ra:text 15 ```Biếnnthuộc vềmake_adder, Nhưngaddsau này vẫn sử dụng nó. CPython hỗ trợ điều này bằng cách di chuyển các biến đã ghi vào đối tượng ô. Hàm bên trong giữ các tham chiếu đến các ô đó.

39.1 Hàm lồng nhau

Hàm lồng nhau là hàm được xác định bên trong một hàm khác.```python def outer(): def inner(): return 1

return inner

```cácdef innercâu lệnh thực thi khiouterchạy. Nó tạo ra một đối tượng hàm và liên kết nó với tên cục bộinner.

Đang gọiouter()trả về đối tượng hàm đó:python fn = outer() print(fn()) Đối tượng hàm choinnerchứa:text code object globals dictionary defaults keyword defaults annotations closure cells, if needed Nếu nhưinnerkhông tham chiếu đến các biến cục bộ bên ngoài, nó không cần đóng.

39.2 Biến miễn phí

Biến tự do là biến được sử dụng bởi đối tượng mã nhưng được xác định trong phạm vi kèm theo.```python def outer(): x = 10

def inner():
    return x

return inner

```Bên tronginner, xlà một biến tự do.

Bạn có thể kiểm tra điều này:```python def outer(): x = 10

def inner():
    return x

return inner

fn = outer()

print(fn.code.co_freevars) Đầu ra:text ('x',) ```Đối tượng mã bên trong ghi lại những gì nó cầnxtừ bên ngoài.

39.3 Biến ô

Biến ô là biến cục bộ phải được hàm bên trong nắm bắt.```python def outer(): x = 10

def inner():
    return x

return inner

```Vìouter, xlà một biến ô vì hàm bên trong sử dụng nó.

Thanh tra:python print(outer.__code__.co_cellvars) Đầu ra:text ('x',) Biến tương tự được nhìn từ hai hướng:```text outer: x is a cell variable

inner: x is a free variable


Mt biến cc b bình thường tn ti trong mt khe khung.```python
def f():
    x = 10
    return x
```Sau đó`f`quay tr li, khung ca nó có th b phá hy. Các khe cc b ca nó biến mt.

Nhưng điu này không th hot động đối vi vic đóng ca:```python
def outer():
    x = 10

    def inner():
        return x

    return inner
```Sau đó`outer`tr li,`inner`vn cn`x`.

CPython gii quyết điu này bng cách lưu tr`x`trong mt đối tượng ô.

V mt khái nim:```text
outer frame
    x slot points to cell
        cell contains 10

inner function
    closure tuple points to same cell
```Khi`outer`tr li, khung có th biến mt, nhưng ô vn tn ti vì`inner`tham kho nó.

## 39.5 Đối tượng di động

Đối tượng ô là mt thùng cha nh cha tham chiếu đến mt đối tượng Python khác.

V mt khái nim:```text
cell
    contents -> object
```Vì:```python
def outer():
    x = 10
    def inner():
        return x
    return inner
```vic đóng ca trông ging như:```text
inner function
    __closure__:
        cell for x
            contents: 10
```Kim tra nó:```python
fn = outer()

print(fn.__closure__)
print(fn.__closure__[0].cell_contents)
```Hình dng đầu ra:```text
(<cell at 0x...: int object at 0x...>,)
10
```Tế bào, ch không phi toàn b khung bên ngoài, mi là th tn ti.

## 39.6 Bộ đóng hàm

Mt đối tượng hàm có`__closure__`thuc tính.```python
def outer():
    x = 10

    def inner():
        return x

    return inner

fn = outer()

print(fn.__closure__)

__closure__là một trong haiNonehoặc một bộ các đối tượng ô.

Đối với ví dụ này:text fn.__closure__ -> (cell_for_x,) Thứ tự các ô tương ứng vớifn.__code__.co_freevars.

print(fn.__code__.co_freevars)
for cell in fn.__closure__:
    print(cell.cell_contents)
```Đầu ra:```text
('x',)
10
```## 39.7 Đọc siêu dữ liệu đóng

Sử dụng  dụ này:```python
def outer(a):
    b = 2

    def inner(c):
        return a + b + c

    return inner

fn = outer(10)

print(outer.__code__.co_cellvars)
print(fn.__code__.co_freevars)
print(fn.__closure__)
```Hình dạng đầu ra:```text
('a', 'b')
('a', 'b')
(<cell ...>, <cell ...>)
```Hàm ngoài  các biến ô`a``b`.

Hàm bên trong  các biến miễn phí`a``b`.

Hàm trả về mang các ô cho cả hai.

## 39,8`LOAD_DEREF`Các biến đóng được truy cập bằng mã byte dereference.

:```python
def outer():
    x = 10

    def inner():
        return x

    return inner

innerkhông sử dụngLOAD_FASTx. Nó sử dụng quyền truy cập đóng cửa.

Về mặt khái niệm:```text LOAD_DEREF x RETURN_VALUE


`LOAD_DEREF`đọc nội dung của một ô.

Tương tự, việc lưu trữ vào một biến đóng sử dụng lệnh lưu trữ theo định hướng quy định.

## 39.9 Tháo rời một đóng cửa

sử dụng`dis`:

```python
import dis

def outer():
    x = 10

    def inner():
        return x

    return inner

dis.dis(outer)

fn = outer()
dis.dis(fn)
```Hãy tìm:```text
MAKE_CELL
LOAD_CLOSURE
MAKE_FUNCTION
LOAD_DEREF
STORE_DEREF
```Hướng dẫn chính xác khác nhau tùy theo phiên bản CPython, nhưng các hoạt động khái niệm ổn định:```text
create cell for captured local
create inner function with closure
load from closure cell inside inner
```## 39.10 Tạo đóng cửa

Khi CPython tạo một đối tượng hàm cho một hàm lồng nhau,  sẽ gắn các ô đóng nếu hàm lồng nhau cần các biến tự do.

Về mặt khái niệm:```text
outer executes
    create cell for x
    load inner code object
    load closure cell for x
    make function object with closure
    return function object
```:```python
def outer():
    x = 10

    def inner():
        return x

    return inner
```hàm trả về :```text
inner.__code__
inner.__globals__
inner.__closure__ = (cell_for_x,)
```Bộ đóng cửa đó  như thế nào`inner`thấy`x`.

## 39.11 Closure ghi lại các biến, không phải giá trị

Việc đóng cửa ghi lại các biến thông qua các ô chứ không phải ảnh chụp nhanh các giá trị.```python
def outer():
    x = 1

    def inner():
        return x

    x = 2
    return inner

fn = outer()
print(fn())
```Đầu ra:```text
2
```Hàm bên trong xem nội dung hiện tại của ô. Ô này đã được cập nhật trước đó`outer`đã quay trở lại.

Về mặt khái niệm:```text
cell x initially contains 1
cell x later contains 2
inner reads cell x
```## 39.12 Ô dùng chung

Nhiều chức năng bên trong  thể chia sẻ cùng một ô.```python
def outer():
    x = 0

    def get():
        return x

    def set_value(v):
        nonlocal x
        x = v

    return get, set_value

get, set_value = outer()

print(get())
set_value(10)
print(get())
```Đầu ra:```text
0
10
```Cả hai hàm đều tham chiếu cùng một ô cho`x`.

```text
get.__closure__[0]       -> cell x
set_value.__closure__[0] -> same cell x
```Ô cung cấp liên kết  thể thay đổi được chia sẻ.

## 39,13`nonlocal`

`nonlocal`báo cho trình biên dịch biết rằng phép gán phải nhắm mục tiêu một biến hàm kèm theo, chứ không phải tạo một biến cục bộ mới.```python
def outer():
    x = 0

    def inc():
        nonlocal x
        x += 1
        return x

    return inc
```Không `nonlocal`, bài tập làm cho`x`địa phương đến`inc`:

```python
def outer():
    x = 0

    def bad():
        x += 1
        return x

    return bad
```Đang gọi`bad()`tăng lên`UnboundLocalError`bởi `x += 1`cố gắng đọc địa phương`x`trước khi   giá trị.

Với`nonlocal`, CPython thực hiện các hoạt động không quy định đối với ô bên ngoài.

## 39,14`global`vs`nonlocal`

`global`nhắm mục tiêu không gian tên -đun.```python
x = 0

def f():
    global x
    x = 10

nonlocalnhắm mục tiêu một phạm vi chức năng kèm theo.```python def outer(): x = 0

def inner():
    nonlocal x
    x = 10

| Tuyên b | Mc tiêu |
|---|---|
|`global x`| Mô-đun t đin toàn cu |
|`nonlocal x`| Phm vi chc năng kèm theo gn nht vi`x`|
| không khai báo vi bài tp | Phm vi địa phương hin ti |`nonlocal`không th nhm mc tiêu mt mô-đun toàn cu. Nó đòi hi mt ràng buc chc năng kèm theo.

## 39.15 Phân tích phạm vi và kết thúc

Trình biên dch xác định b cc đóng trong quá trình phân tích bng ký hiu.

Đối vi mi khi mã, nó phân loi tên thành:```text
local
global explicit
global implicit
free
cell
```Ví d:```python
def outer():
    x = 1

    def inner():
        return x
```Phân loi:```text
outer:
    x = local, promoted to cell
    inner = local

inner:
    x = free
```S phân loi này quyết định hướng dn mã byte nào được phát ra.```text
local variable    -> LOAD_FAST / STORE_FAST
global name       -> LOAD_GLOBAL / STORE_GLOBAL
closure variable  -> LOAD_DEREF / STORE_DEREF
```## 39.16 Thời gian đóng cửa

Mt ô tn ti min là có th gì đó tham chiếu đến nó.

Ch s hu chung:```text
function closure tuple
active frame
generator frame
coroutine frame
another cell or object graph
```Ví d:```python
def outer():
    x = [1, 2, 3]

    def inner():
        return x

    return inner

fn = outer()
```Danh sách vn còn tn ti:```text
fn
    __closure__
        cell
            list [1, 2, 3]
```Khi`fn`tr nên không th truy cp được, b d liu đóng và ô có th được gii phóng và danh sách có th được gii phóng nếu không có tham chiếu nào khác tn ti.

## 39.17 Việc đóng cửa thường không giữ được toàn bộ khung hình

Mt s hiu lm ph biến là vic đóng gi cho toàn b khung bên ngoài tn ti.

Thông thường thì không.```python
def outer():
    a = "captured"
    b = "not captured"

    def inner():
        return a

    return inner
```Hàm tr v cn`a`, nhưng không`b`.

V mt khái nim:```text
inner keeps cell for a
inner does not keep b
outer frame can be destroyed
```Điu này hiu qu hơn vic bo toàn toàn b khung.

Tuy nhiên, nếu bn thân mt đối tượng khung được ghi li thông qua quá trình xem xét ni tâm thì nó có th gi cho tt c các đối tượng cc b còn sng.

## 39.18 Ràng buộc muộn trong vòng lặp

Đóng ca nm bt các biến, không phi giá tr trên mi ln lp.```python
funcs = []

for i in range(3):
    funcs.append(lambda: i)

print([f() for f in funcs])
```Đầu ra:```text
[2, 2, 2]
```Tt c các lambda đều đóng trên cùng mt biến`i`. Sau khi vòng lp kết thúc,`i`là`2`.

Đây là ràng buc mun: giá tr được tra cu khi hàm chy ch không phi khi nó được to.

## 39.19 Ghi lại các giá trị hiện tại bằng giá trị mặc định

S dng đối s mc định để nm bt giá tr hin ti.```python
funcs = []

for i in range(3):
    funcs.append(lambda i=i: i)

print([f() for f in funcs])
```Đầu ra:```text
[0, 1, 2]
``` đây, mi lambda có giá tr đối s mc định riêng.

Điu này s dng các giá tr mc định ca hàm, không phi các ô đóng.

V mt khái nim:```text
lambda i=0: i
lambda i=1: i
lambda i=2: i
```## 39.20 Đóng cửa trong sự hiểu biết

S hiu biết có phm vi riêng ca chúng, nhưng s đóng ca bên trong chúng vn có th cho thy s ràng buc mun.```python
funcs = [lambda: x for x in range(3)]
print([f() for f in funcs])
```Đầu ra:```text
[2, 2, 2]
```Biến vòng lp`x`thuc phm vi hiu và tt c các lambda đều đóng trên cùng mt ô đó.

S dng giá tr mc định để nm bt các giá tr trên mi ln lp:```python
funcs = [lambda x=x: x for x in range(3)]
print([f() for f in funcs])
```Đầu ra:```text
[0, 1, 2]
```## 39.21 Đóng cửa và khả năng thay đổi

Mt bao đóng có th tham chiếu mt đối tượng có th thay đổi.```python
def outer():
    xs = []

    def add(x):
        xs.append(x)
        return xs

    return add

add = outer()

print(add(1))
print(add(2))
```Đầu ra:```text
[1]
[1, 2]
```KHÔNG`nonlocal`là cn thiết vì hàm này làm thay đổi đối tượng danh sách. Nó không ràng buc li tên`xs`.

Điu này hot động:```python
xs.append(x)
```Điu này cn`nonlocal`:

```python
xs = xs + [x]
```Hình thc th hai gán li tên.

## 39.22 Rebound vs Đột biến

So sánh:```python
def outer():
    xs = []

    def add(x):
        xs.append(x)

    return add
```Và:```python
def outer():
    xs = []

    def add(x):
        xs = xs + [x]

    return add
```Cái đầu tiên làm thay đổi đối tượng được tham chiếu bi`xs`.

Th hai gán cho`xs`, do đó trình biên dch x lý`xs`như địa phương để`add`tr khi được khai báo`nonlocal`.

Đảo ngược chính xác:```python
def outer():
    xs = []

    def add(x):
        nonlocal xs
        xs = xs + [x]
        return xs

    return add
```## 39.23 Đóng cửa và các nhà máy hoạt động

Closure thường được s dng cho các nhà máy chc năng.```python
def power(exp):
    def apply(x):
        return x ** exp
    return apply

square = power(2)
cube = power(3)

print(square(5))
print(cube(5))
```Đầu ra:```text
25
125
```Mi cuc gi ti`power`to mt ô mi cho`exp`.

```text
square closure:
    exp = 2

cube closure:
    exp = 3
```Đối tượng mã cho`apply`có th được chia s, nhưng các ô đóng khác nhau.

## 39.24 Đóng cửa và trang trí

Người trang trí thường s dng các bao đóng.```python
def log_calls(fn):
    def wrapper(*args, **kwargs):
        print("calling", fn.__name__)
        return fn(*args, **kwargs)

    return wrapper
```S dng:```python
@log_calls
def add(a, b):
    return a + b
```V mt khái nim:```python
def add(a, b):
    return a + b

add = log_calls(add)
```S tr li`wrapper`đóng trên bn gc`fn`.

```text
wrapper.__closure__
    cell for fn -> original add function
```## 39,25 Đóng cửa và trạng thái

Closure có th lưu tr trng thái riêng tư.```python
def counter():
    n = 0

    def inc():
        nonlocal n
        n += 1
        return n

    return inc

c = counter()

print(c())
print(c())
```Đầu ra:```text
1
2
```Nhà nước`n`không được lưu tr trên mt phiên bn. Nó được lưu tr trong mt ô đóng ca.

Điu này tương t như mt đối tượng nh vi mt phương thc và trng thái riêng tư.

## 39.26 Trạng thái đóng so với Trạng thái đối tượng

Phiên bn đóng ca:```python
def counter():
    n = 0

    def inc():
        nonlocal n
        n += 1
        return n

    return inc
```Phiên bn đối tượng:```python
class Counter:
    def __init__(self):
        self.n = 0

    def inc(self):
        self.n += 1
        return self.n
```So sánh:

| Tính năng | Đóng ca | Đối tượng |
|---|---|---|
| Lưu tr nhà nước | Biến ô | Thuc tính sơ thm |
| Nhiu hot động | Ít thun tin hơn | T nhiên |
| Hướng ni | Ít rõ ràng hơn | Rõ ràng hơn |
| Trng thái gi li nh | Phù hp tt | Phù hp tt |
| Hành vi phong phú | Lúng túng | Tt hơn |

Đóng ca là tt nht cho trng thái b bt nh. Các lp hc tt hơn cho các giao thc ln hơn.

## 39.27 Đóng cửa và Chu kỳ tham chiếu

Vic đóng ca có th tham gia vào các chu k.```python
def outer():
    funcs = []

    def inner():
        return funcs

    funcs.append(inner)
    return inner

fn = outer()
```Biu đồ tham kho:```text
inner function
    closure cell
        funcs list
            inner function
```Chu trình này có th được thu thp bi trình thu gom rác tun hoàn ca CPython khi không th truy cp được.

Các chu trình liên quan đến khâu quyết toán hoc ngun lc bên ngoài cn được quan tâm nhiu hơn.

## 39.28 Đóng và lưu giữ bộ nhớ

Đóng ca có th gi li các đối tượng ln.```python
def make_reader():
    data = bytearray(100_000_000)

    def read():
        return data[0]

    return read

reader = make_reader()
```Cái ln`data`đối tượng vn còn sng min là`reader`làm.

Chui lưu gi:```text
reader function
    closure tuple
        cell
            large bytearray
```Nếu vic đóng không còn cn đối tượng ln na, hãy xóa hoc tránh chp đối tượng đó.

## 39.29 Tránh vô tình bị bắt

Điu này nm bt`self`:

```python
class C:
    def make_callback(self):
        def callback():
            return self.value
        return callback
```Cuc gi li được tr v s gi cho phiên bn này tn ti.

Đôi khi điu này được d định. Đôi khi nó to ra s gi chân không ng ti.

Bn ch có th nm bt giá tr cn thiết:```python
class C:
    def make_callback(self):
        value = self.value

        def callback():
            return value

        return callback
```Bây gi cuc gi li tiếp tc`value`, không nht thiết là toàn b trường hp.

## 39.30 Kiểm tra nội dung đóng cửa

s dng`__closure__`cn thn:```python
def outer():
    x = {"a": 1}

    def inner():
        return x

    return inner

fn = outer()

for name, cell in zip(fn.__code__.co_freevars, fn.__closure__):
    print(name, cell.cell_contents)
```Đầu ra:```text
x {'a': 1}
```Điu này hu ích cho vic hc và g li, nhưng mã sn xut hiếm khi ph thuc vào ni b đóng.

## 39.31 Ô trống

Ô đóng có th trng trong mt s trường hp cnh.

Các mu ví d liên quan đến vic xóa có th to ra các ô trng:```python
def outer():
    x = 1

    def inner():
        return x

    del x
    return inner
```Gi:```python
fn = outer()
fn()
```gây ra li vì ô không còn ni dung na.

Truy cp`cell.cell_contents`đối vi mt ô trng tăng lên`ValueError`.

## 39.32 Đóng cửa và`del`Việc xóa một biến không cục bộ sẽ xóa ô.```python
def outer():
    x = 1

    def delete():
        nonlocal x
        del x

    def read:
        return x

    return read, delete
```Phiên bn đã sa:```python
def outer():
    x = 1

    def delete():
        nonlocal x
        del x

    def read():
        return x

    return read, delete
```S dng:```python
read, delete = outer()
print(read())
delete()
print(read())
```trn chung kết`read()`tăng vì ô trng.

## 39.33 Đóng cửa và mặc định là khác nhau

Giá tr mc định được lưu tr trên đối tượng hàm.```python
def f(x=[]):
    return x
```Các ô đóng ca được lưu tr trong`__closure__`.

```python
def outer():
    x = []

    def inner():
        return x

    return inner
```Thanh tra:```python
print(f.__defaults__)
print(outer().__closure__)
```H gii quyết các vn đề khác nhau.

| Cơ chế | Ca hàng |
|---|---|
| Đối s mc định | Giá tr được s dng khi đối s b b qua |
| Tế bào đóng ca | Biến t phm vi kèm theo |

Th thut đối s mc định để liên kết mun hot động vì các giá tr mc định được đánh giá ti thi đim to hàm.

## 39.34 Đóng cửa và Lambdas`lambda`các hàm tuân theo các quy tắc đóng tương tự như`def`.

```python
def outer():
    x = 10
    return lambda y: x + y

fn = outer()
print(fn(5))
```Đầu ra:```text
15
```Lambda có mt biến min phí`x`.

```python
print(fn.__code__.co_freevars)
print(fn.__closure__[0].cell_contents)
```Lambda ch là mt biu thc hàm thu gn. Nó không có mô hình đóng ca đặc bit.

## 39.35 Đóng cửa và Máy phát điện

Mt trình to có th đóng các biến.```python
def outer(limit):
    def gen():
        for i in range(limit):
            yield i

    return gen

make = outer(3)
print(list(make()))
```Chc năng máy phát đin đóng li`limit`.

Khi`make()`được gi, nó to ra mt đối tượng máy phát đin. Đối tượng trình to đó có th truy cp vào ô đóng.

Có hai lp:```text
generator function
    closure cell for limit

generator object
    suspended frame when running
    references generator function/code/closure state
```## 39.36 Đóng và Coroutine

Các hàm không đồng b cũng có th đóng các biến.```python
def outer(delay):
    async def wait_then_return(value):
        await sleep(delay)
        return value

    return wait_then_return
```Chc năng async đóng li`delay`.

Vic gi nó s to ra mt đối tượng coroutine. Trong khi b treo, coroutine vn gi trng thái khung và hàm mang các ô đóng.

Điu này có th gi li các đối tượng b bt trong thi gian ch đợi.

## 39.37 Hiệu suất đóng cửa

Truy cp mt biến đóng thường chm hơn so vi truy cp cc b nhanh.

Địa phương nhanh:```text
LOAD_FAST
```Biến đóng ca:```text
LOAD_DEREF

LOAD_DEREFphải đọc qua một ô.

Trong hầu hết các mã, chi phí này là nhỏ. Trong các vòng lặp rất nóng, ràng buộc cục bộ có thể quan trọng.

Ví dụ:python def outer(value): def inner(xs): v = value total = 0 for x in xs: total += x + v return total return inner Đây,vlà một người địa phương nhanh chóng bên tronginner, trong khivalueđược đọc từ một ô một lần.

39.38 Gỡ lỗi đóng cửa

Khi gỡ lỗi hành vi đóng, hãy kiểm tra:python fn.__code__.co_freevars fn.__closure__ cell.cell_contents Ví dụ:```python def outer(): x = 1 y = 2

def inner():
    return x + y

return inner

fn = outer()

for name, cell in zip(fn.code.co_freevars, fn.closure): print(name, cell.cell_contents)


## 39.39 Những hiểu lầm thường gặp

| Hiu lm | Đúng mu |
|---|---|
| Giá tr sao chép đóng ca | H nm bt các biến thông qua các ô |
| Vic đóng ca gi cho toàn b khung bên ngoài tn ti | Thông thường nó ch gi nhng ô cn thiết |
|`nonlocal`có nghĩa là toàn cu | Nó nhm đến mt phm vi chc năng kèm theo |
| Thay đổi nhu cu danh sách đã chp`nonlocal`| Ch cn đảo ngược tên`nonlocal`|
| Lambdas có quy tc đóng khác nhau | Lambda và`def`s dng cùng mt mô hình đóng ca |
| Vic đóng vòng lp nm bt tng giá tr lp li | H nm bt biến vòng lp |
| Mc định và đóng ca ging nhau | Giá tr lưu tr mc định; đóng ca các tế bào lưu tr |
| Các biến đóng ca là các biến cc b nhanh | Chúng được truy cp thông qua các ô |

##39.40 Chiến lược đọc

Bt đầu vi:```python
def outer():
    x = 10

    def inner():
        return x

    return inner
```Thanh tra:```python
import dis

fn = outer()

print(outer.__code__.co_cellvars)
print(fn.__code__.co_freevars)
print(fn.__closure__)
print(fn.__closure__[0].cell_contents)

dis.dis(outer)
dis.dis(fn)
```Sau đó kim tra:```text
nonlocal rebinding
multiple inner functions sharing one variable
lambda inside loops
default-argument capture
closures holding large objects
closures inside generators
closures inside async functions
```Đối vi mi trường hp, theo dõi:```text
which scope binds the name
whether the name becomes a cell variable
which inner function sees it as a free variable
which function owns the closure tuple
how long the cell remains alive
```## 39.41 Tóm tắt chương

Các bao đóng là cơ chế ca CPython để cho phép các hàm lng nhau truy cp các biến t phm vi hàm kèm theo. Khi mt biến cc b bên ngoài được hàm bên trong s dng, CPython s lưu tr biến đó trong mt ô. Hàm bên trong mang mt b đóng cha các ô cn thiết.

Mô hình ct lõi là:```text
outer function local used by inner function
    
local becomes a cell variable
    
inner function records it as a free variable
    
function object stores closure tuple
    
cell remains alive after outer frame returns
    
inner function reads or writes cell contents
```Các bao đóng gii thích các hàm lng nhau, trình trang trí, nhà máy hàm, trng thái gi li,`nonlocal`, liên kết mun trong các vòng lp và duy trì b nh thông qua các biến được ghi li.