Có, The Zen of Python nói "Phẳng tốt hơn lồng nhau", tuy nhiên nó không phải là đặc điểm duy nhất mà chúng tôi quan tâm; nó cũng nói "Đơn giản là tốt hơn so với phức tạp". Vẻ đẹp của with
là nó thực sự tuân thủ cả hai nguyên tắc như tôi sẽ giải thích bên dưới.
Bất cứ khi nào bạn thấy mình đang suy nghĩ về triết lý về một tính năng bằng Python, có lẽ bạn nên tìm hiểu về động lực đằng sau đối tượng địa lý. Trong trường hợp này PEP 343 -- The "with" Statement nói nó lên phía trước một cách trừu tượng:
PEP này thêm một tuyên bố mới "với" với ngôn ngữ Python để làm cho nó thể yếu tố ra sử dụng tiêu chuẩn của try/cuối cùng báo cáo.
Việc tính toán mã đơn giản và dễ đọc hơn. Tuy nhiên,
PEP 343 đi sâu hơn việc cung cấp một số đường cú pháp đơn giản. Nó thiết lập một giao thức quản lý bối cảnh:
Khái niệm ngay sau với từ khóa vào báo cáo kết là một "biểu hiện bối cảnh" như biểu hiện cung cấp các đầu mối chính như đối với môi trường runtime người quản lý bối cảnh thiết lập cho thời hạn của phần tử tuyên bố.
Sử dụng giao thức người quản lý ngữ cảnh, người viết API có thể giúp che giấu sự phức tạp và đảm bảo thu thập/giải phóng tài nguyên chính xác trong ngữ cảnh đa luồng.
Nhưng vẻ đẹp thực sự của tuyên bố with
được hiển thị trong Ví dụ 12 PEP 343 mà giải thích rằng:
A "lồng" quản lý bối cảnh đó tự động làm tổ được cung cấp bối cảnh từ trái sang phải để tránh thụt lề quá mức.
Sử dụng quản lý nested()
bối cảnh mà bạn có thể lấy mã trông như thế này:
with a as x:
with b as y:
with c as z:
# Perform operation
và biến nó thành này:
with nested(a, b, c) as (x, y, z):
# Perform operation
Lưu ý rằng nested()
đã được giới thiệu trong Python 2.5, nhưng kể từ phiên bản 2.7, nó không còn được dùng để ủng hộ dạng cú pháp quản lý ngữ cảnh đa ngữ này:
with a as x, b as y, c as z:
# Perform operation
Rõ ràng không chỉ đơn giản và dễ đọc hơn mà còn phẳng hơn nhiều so với lồng nhau. Vì vậy, sử dụng with
là đi theo con đường của 無爲 :)
UPDATE: Để đối phó với comments on Simeon Visser's answer đây là một ví dụ khi bạn có thể sử dụng nhiều nhà quản lý bối cảnh để mở nhiều hơn một tập tin cùng một lúc, khi bạn muốn nén các nội dung của hai (hay nhiều) tập tin với nhau như vậy mà nếu mở một trong các tập tin không nó sẽ làm cho toàn bộ điều thất bại và đóng đúng cách mỗi tập tin đã được mở:
from itertools import izip
with open("/etc/passwd") as a, open("/etc/group") as b, open("/etc/shadow") as c:
for lines in izip(a,b,c):
print map(lambda x: x.split(':')[0], lines)
Run ví dụ này hai lần; một lần như là một gốc và một lần như người dùng bình thường. Giả sử bạn lưu tệp này là ziptogether.py
trước tiên hãy thử gọi nó là gốc với sudo python ziptogether.py
và nó sẽ thành công, nhưng gọi nó là người dùng bình thường với python ziptogether.py
sẽ thất bại vì bạn không có quyền đọc /etc/shadow
. Khi trình quản lý ngữ cảnh thất bại sẽ đảm bảo rằng các tệp đã được mở thành công trước khi lỗi được đóng đúng cách khi thực thi di chuyển ra ngoài phạm vi của câu lệnh with
.
Hầu hết thời gian tôi chỉ cho phép IOError truyền và bắt nó ở một nơi khác. – Dikei
Nhiều như tôi không đồng ý với tiền đề của câu hỏi này, tôi phải cung cấp cho bạn các đạo cụ để làm cho tôi quay trở lại và đọc lại PEP [342] (http: //www.python.org/dev/peps/pep-0342 /) và [343] (http://www.python.org/dev/peps/pep-0343/) – kojiro