Câu hỏi đã được trả lời bởi aaronasterling
Tuy nhiên, ai đó có thể quan tâm đến cách các biến được lưu trữ dưới mui xe.
Trước khi đến với đoạn trích:
Đóng cửa là các chức năng kế thừa các biến từ môi trường kèm theo của chúng. Khi bạn chuyển một hàm gọi lại dưới dạng đối số cho một hàm khác sẽ thực hiện I / O, hàm gọi lại này sẽ được gọi sau đó và hàm này sẽ - gần như kỳ diệu - ghi nhớ bối cảnh mà nó được khai báo, cùng với tất cả các biến có sẵn trong bối cảnh đó.
Nếu một hàm không sử dụng các biến miễn phí thì nó không tạo thành một bao đóng.
Nếu có một cấp độ bên trong khác sử dụng các biến miễn phí - tất cả các cấp độ trước đó sẽ lưu môi trường từ vựng (ví dụ ở cuối)
thuộc tính hàm func_closure
trong python <3.X hoặc __closure__
trong python> 3.X lưu các biến miễn phí.
Mọi hàm trong python đều có thuộc tính đóng này, nhưng nó không lưu bất kỳ nội dung nào nếu không có biến miễn phí.
ví dụ: của các thuộc tính đóng nhưng không có nội dung bên trong vì không có biến miễn phí.
>>> def foo():
... def fii():
... pass
... return fii
...
>>> f = foo()
>>> f.func_closure
>>> 'func_closure' in dir(f)
True
>>>
Lưu ý: BIỂU TƯỢNG MIỄN PHÍ LÀ PHẢI TẠO MỘT ĐÓNG
Tôi sẽ giải thích bằng cách sử dụng đoạn mã giống như trên:
>>> def make_printer(msg):
... def printer():
... print msg
... return printer
...
>>> printer = make_printer('Foo!')
>>> printer() #Output: Foo!
Và tất cả các hàm Python đều có thuộc tính bao đóng, vì vậy hãy kiểm tra các biến kèm theo được liên kết với hàm đóng.
Đây là thuộc tính func_closure
cho hàmprinter
>>> 'func_closure' in dir(printer)
True
>>> printer.func_closure
(<cell at 0x108154c90: str object at 0x108151de0>,)
>>>
Các closure
thuộc tính trả về một tuple của các đối tượng tế bào có chứa thông tin chi tiết của các biến được định nghĩa trong phạm vi kèm theo.
Phần tử đầu tiên trong func_clenses có thể là Không hoặc một tuple các ô có chứa các ràng buộc cho các biến miễn phí của hàm và nó chỉ đọc.
>>> dir(printer.func_closure[0])
['__class__', '__cmp__', '__delattr__', '__doc__', '__format__', '__getattribute__',
'__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'cell_contents']
>>>
Ở đây trong đầu ra ở trên bạn có thể thấy cell_contents
, hãy xem những gì nó lưu trữ:
>>> printer.func_closure[0].cell_contents
'Foo!'
>>> type(printer.func_closure[0].cell_contents)
<type 'str'>
>>>
Vì vậy, khi chúng ta gọi hàm printer()
, nó truy cập giá trị được lưu trữ bên trong cell_contents
. Đây là cách chúng tôi có đầu ra là 'Foo!'
Một lần nữa tôi sẽ giải thích bằng đoạn trích trên với một số thay đổi:
>>> def make_printer(msg):
... def printer():
... pass
... return printer
...
>>> printer = make_printer('Foo!')
>>> printer.func_closure
>>>
Trong đoạn trích trên, tôi không in thông điệp bên trong chức năng của máy in, vì vậy nó không tạo ra bất kỳ biến miễn phí nào. Vì không có biến miễn phí, sẽ không có nội dung bên trong bao đóng. Đó chính xác là những gì chúng ta thấy ở trên.
Bây giờ tôi sẽ giải thích một đoạn khác để xóa mọi thứ Free Variable
với Closure
:
>>> def outer(x):
... def intermediate(y):
... free = 'free'
... def inner(z):
... return '%s %s %s %s' % (x, y, free, z)
... return inner
... return intermediate
...
>>> outer('I')('am')('variable')
'I am free variable'
>>>
>>> inter = outer('I')
>>> inter.func_closure
(<cell at 0x10c989130: str object at 0x10c831b98>,)
>>> inter.func_closure[0].cell_contents
'I'
>>> inn = inter('am')
Vì vậy, chúng ta thấy rằng một thuộc func_closure
tính là một bộ các ô đóng , chúng ta có thể giới thiệu chúng và nội dung của chúng một cách rõ ràng - một ô có thuộc tính "cell_contents"
>>> inn.func_closure
(<cell at 0x10c9807c0: str object at 0x10c9b0990>,
<cell at 0x10c980f68: str object at 0x10c9eaf30>,
<cell at 0x10c989130: str object at 0x10c831b98>)
>>> for i in inn.func_closure:
... print i.cell_contents
...
free
am
I
>>>
Ở đây khi chúng tôi gọi inn
, nó sẽ tham chiếu tất cả các biến miễn phí lưu để chúng tôi nhận đượcI am free variable
>>> inn('variable')
'I am free variable'
>>>