2011-08-24 30 views
27

Pickle của Python (Tôi đang nói tiêu chuẩn Python 2.5/2.6/2.7 ở đây) không thể chọn ổ khóa, các đối tượng tập tin, vv ..Tại sao máy phát điện không thể được ngâm?

Nó cũng không thể phát điện và biểu thức lambda (hoặc bất kỳ mã ẩn danh nào) chỉ lưu trữ các tham chiếu tên của cửa hàng.

Trong trường hợp khóa và các tính năng phụ thuộc vào hệ điều hành, lý do lý do tại sao bạn không thể chọn chúng là hiển nhiên và có ý nghĩa.

Nhưng tại sao bạn không thể chọn máy phát điện?


Note: chỉ cho rõ ràng - Tôi quan tâm đến những lý do cơ bản (hoặc giả định và lựa chọn mà đi vào đó quyết định thiết kế) tại sao, không phải trong "bởi vì nó cung cấp cho bạn một Pickle lỗi".

Tôi nhận ra câu hỏi có mục tiêu rộng một chút, vì vậy đây là nguyên tắc bạn trả lời: "Nếu những giả định này được nâng lên, hoặc loại máy phát được cho phép bị hạn chế hơn, máy phát điện sẽ hoạt động trở lại?"

+1

Khi nào thì bạn nên chọn máy phát điện? – NullUserException

+10

@NullUser: Không quá khó tưởng tượng; Bạn đang lặp qua một và bạn muốn dừng chương trình của mình và sau đó tiếp tục lại nơi bạn rời đi sau đó. –

+3

... hoặc tiếp tục cùng một lúc, nhưng từ một chương trình khác (= serializing cũng được sử dụng trong truyền dẫn mạng) – Radim

Trả lời

39

Có rất nhiều thông tin về tính năng này. Đối với "từ chính thức" về vấn đề này, hãy đọc số (closed) Python bugtracker issue.

Lý do cốt lõi, bởi một trong những người đưa ra quyết định, là chi tiết về this blog:

Kể từ khi một máy phát điện được về cơ bản là một chức năng được cải tiến lên, chúng ta sẽ cần phải lưu bytecode của nó, đó là không đảm bảo tương thích ngược giữa các phiên bản của Python và khung của nó, giữ trạng thái của trình tạo như các biến địa phương, các bao đóng và con trỏ lệnh. Và sau này là khá cồng kềnh để thực hiện, vì nó về cơ bản đòi hỏi phải làm cho toàn bộ thông dịch viên có thể lựa chọn. Vì vậy, bất kỳ sự hỗ trợ nào cho máy phát điện tẩy sẽ đòi hỏi một số lượng lớn các thay đổi đối với lõi của CPython.

Bây giờ nếu một đối tượng không được hỗ trợ bởi pickle (ví dụ: xử lý tệp, ổ cắm, kết nối cơ sở dữ liệu, v.v.) xảy ra trong biến cục bộ của trình tạo, thì trình tạo đó không thể tự động được chọn, bất kể hỗ trợ pickle cho máy phát điện, chúng tôi có thể thực hiện. Vì vậy, trong trường hợp đó, bạn vẫn cần cung cấp các phương thức tùy chỉnh __getstate____setstate__. Vấn đề này ám chỉ bất kỳ hỗ trợ tẩy cho máy phát điện thay vì hạn chế.

Và hai giải pháp đề xuất được nhắc đến:

Dù sao, nếu bạn cần cho một tính năng như vậy, sau đó nhìn vào Stackless Python mà làm tất cả các bên trên. Và kể từ khi thông dịch viên của Stackless là có thể chọn, bạn cũng có được quá trình di chuyển miễn phí. Điều này có nghĩa là bạn có thể làm gián đoạn một tasklet (tên cho các chủ đề màu xanh lá cây của Stackless), chọn nó, gửi dưa chuột tới một máy khác, tháo nó ra, tiếp tục lại tác vụ và voilà bạn vừa di chuyển một tiến trình. Đây là tính năng tuyệt vời! Tuy nhiên, theo quan điểm khiêm tốn của tôi, giải pháp tốt nhất cho vấn đề này là viết lại các máy phát như các trình lặp đơn giản (tức là, một với phương thức __next__). Iterator là dễ dàng và hiệu quả không gian khôn ngoan để dưa vì trạng thái của họ là rõ ràng. Tuy nhiên, bạn vẫn cần xử lý các đối tượng đại diện cho một số trạng thái bên ngoài một cách rõ ràng; bạn không thể vượt qua điều này.

+0

Câu trả lời hay, cảm ơn. Tôi đã tìm thấy "generator_tools", một gói Python thuần túy yêu cầu thực hiện điều này. Tôi không thể làm cho nó hoạt động được, vì vậy tôi đoán bạn (và Alexandre) là đúng ... – Radim

+0

Gói đó được đề cập trên http://metaoptimize.com/blog/2009/12/22/why-cant-you -nhóm-máy phát-trong-python-workaround-pattern-cho-tiết kiệm-đào tạo-nhà nước/mà cũng có một mô hình workaround. – agf

+1

Làm thế nào bạn có thể cung cấp câu trả lời và bỏ phiếu "đóng" cùng một lúc? Bây giờ tôi đang tò mò chờ đợi cho "cuộc tranh luận, tranh luận và thảo luận mở rộng" :-) – Radim

19

Bạn thực sự có thể, tùy thuộc vào việc triển khai. PyPyStackless Python cả cho phép điều này (ở một mức độ nào):

Python 2.7.1 (dcae7aed462b, Aug 17 2011, 09:46:15) 
[PyPy 1.6.0 with GCC 4.0.1] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
And now for something completely different: ``Not your usual analyses.'' 
>>>> import pickle 
>>>> gen = (x for x in range(100)) 
>>>> next(gen) 
0 
>>>> pickled = pickle.dumps(gen) 
>>>> next(pickle.loads(pickled)) 
1 

Trong CPython nó cũng có thể tạo ra một iterator object để mô phỏng một máy phát điện pickable.

+0

-1: Tất cả đều đúng, nhưng trả lời một câu hỏi khác. – Radim

+1

@Radim nó trả lời câu hỏi _my_. –

Các vấn đề liên quan