Có chính xác một lý do tại sao những điều sau đây được ưa thích:
with open('filename.txt') as fp:
for line in fp:
print line
Tất cả chúng ta đều bị làm hỏng bởi sơ đồ đếm tham chiếu tương đối xác định của CPython cho việc thu gom rác. Mặt khác, việc triển khai giả thuyết của Python sẽ không nhất thiết phải đóng tệp "đủ nhanh" mà không có with
khối nếu họ sử dụng một số lược đồ khác để lấy lại bộ nhớ.
Khi triển khai như vậy, bạn có thể gặp lỗi "quá nhiều tệp đang mở" từ HĐH nếu mã của bạn mở tệp nhanh hơn trình thu gom rác gọi bộ hoàn thiện trên các thẻ xử lý tệp mồ côi. Cách giải quyết thông thường là kích hoạt GC ngay lập tức, nhưng đây là một hack khó chịu và nó phải được thực hiện bởi mọi chức năng có thể gặp phải lỗi, bao gồm cả các chức năng trong thư viện. Thật là một cơn ác mộng.
Hoặc bạn chỉ có thể sử dụng with
khối.
Câu hỏi thưởng
(Ngừng đọc ngay bây giờ nếu chỉ quan tâm đến các khía cạnh khách quan của câu hỏi.)
Tại sao không có trong giao thức iterator cho các đối tượng tệp?
Đây là một câu hỏi chủ quan về thiết kế API, vì vậy tôi có một câu trả lời chủ quan trong hai phần.
Ở mức độ ruột, điều này cảm thấy sai, bởi vì nó làm cho giao thức iterator thực hiện hai việc riêng biệt, lặp đi lặp lại trên các dòng và đóng tệp xử lý, và thường thì một chức năng trông đơn giản thực hiện hai hành động. Trong trường hợp này, nó cảm thấy đặc biệt tệ bởi vì các trình vòng lặp liên quan theo cách gần như chức năng, dựa trên giá trị với nội dung của tệp, nhưng quản lý xử lý tệp là một nhiệm vụ hoàn toàn riêng biệt. Việc nghiền nát cả hai, vô hình chung, thành một hành động, gây ngạc nhiên cho những người đọc mã và gây khó khăn hơn cho lý do về hành vi của chương trình.
Các ngôn ngữ khác về cơ bản đã đi đến kết luận tương tự. Haskell đã nhanh chóng tán tỉnh cái gọi là "IO lười biếng", cho phép bạn lặp lại một tập tin và nó tự động đóng lại khi bạn đến cuối luồng, nhưng gần như không khuyến khích sử dụng IO lười biếng trong Haskell những ngày này và Haskell Người dùng chủ yếu đã chuyển sang quản lý tài nguyên rõ ràng hơn như Conduit hoạt động giống như with
khối trong Python.
Ở cấp độ kỹ thuật, có một số điều bạn có thể muốn thực hiện với trình xử lý tệp trong Python sẽ không hoạt động tốt nếu lặp lại đóng xử lý tệp. Ví dụ: giả sử tôi cần lặp lại tập tin hai lần:
with open('filename.txt') as fp:
for line in fp:
...
fp.seek(0)
for line in fp:
...
Mặc dù đây là trường hợp sử dụng ít phổ biến hơn, hãy xem xét thực tế rằng tôi có thể vừa thêm ba dòng mã ở dưới cùng vào cơ sở mã hiện có ban đầu có ba dòng trên cùng. Nếu lặp lại đóng tập tin, tôi sẽ không thể làm điều đó. Vì vậy, việc giữ việc lặp lại và quản lý tài nguyên riêng biệt giúp việc soạn các đoạn mã thành một chương trình Python lớn hơn, hoạt động dễ dàng hơn.
Khả năng tương thích là một trong những tính năng sử dụng quan trọng nhất của ngôn ngữ hoặc API.