2010-02-19 29 views
8

Tôi đã nghe nói về đánh giá hoãn lại trong python (ví dụ here), là nó chỉ đề cập đến cách lambdas được đánh giá bởi người phiên dịch chỉ khi chúng được sử dụng? Hay đây là thuật ngữ thích hợp để mô tả cách thức, do thiết kế động của python, nó sẽ không bắt được nhiều lỗi cho đến khi chạy?Đánh giá chậm trong python

Hoặc tôi có thiếu gì đó hoàn toàn không?

Trả lời

8

câu trả lời Dietrich là một tốt nhất, nhưng tôi chỉ muốn thêm rằng hình thức đơn giản nhất của thẩm định hoãn là if tuyên bố:

if True: 
    x = 5 
else: 
    x = y # huh? what is y? 

Mã này phân tích và chạy một cách chính xác, mặc dù mệnh đề else làm cho không có ý nghĩa - y không xác định. Mệnh đề else chỉ được phân tích cú pháp - vì vậy nó phải là cú pháp Python hợp lệ. Điều này có thể được thực sự sử dụng đối với một số mã đơn giản:

if stuff: 
    print stuff.contents 
else: 
    print "no stuff" 

Trong một ngôn ngữ mạnh mẽ gõ này sẽ không làm việc, vì phải gõ stuff.contents đòi hỏi stuff là của một loại nhất định mà có một thuộc tính contents. Trong Python, vì đánh giá chậm trễ của các câu lệnh trong if, điều này không nhất thiết phải đúng. stuff có thể là None rõ ràng là không có thuộc tính và trình thông dịch sẽ chỉ nhận mệnh đề else mà không thực hiện điều khoản đầu tiên. Do đó đây là Python hợp lệ và thậm chí là một thành ngữ, làm cho mã đơn giản hơn.

Reference discussion

+7

Tôi nghĩ rằng bạn đang bối rối hệ thống kiểu và đánh giá lười biếng trong ví dụ thứ 2 của bạn. Ngôn ngữ đánh máy "mạnh" có thể sử dụng đánh giá lười biếng để thực hiện các thủ thuật gọn gàng. Ví dụ. Haskell có một hệ thống kiểu tĩnh rất mạnh với rất nhiều đánh giá lười biếng! Không giống như Python, 'if-then-else' phải kiểm tra kiểu, nhưng khác với việc đánh giá được hoãn lại. Ví dụ, bạn có thể viết 'nếu True thì 5 else undefined', và điều này biên dịch và chạy tốt (và kết quả là 5, như mong đợi). Đó là 'if-else' của bạn hoạt động trong Python mặc dù nó không gõ-kiểm tra trong một ngôn ngữ tĩnh là không liên quan đến chiến lược đánh giá. –

14

Đánh giá chậm là khi biểu thức không được đánh giá cho đến khi cần. Trong hầu hết các ngôn ngữ, bạn sử dụng một cái gì đó như lambda để thực hiện công việc này. Dưới đây là một ví dụ contrived cho thấy một phần của khái niệm:

def list_files(): 
    for fn in os.listdir('.'): 
     yield fn, lambda: open(fn, 'r').read() 


for fn, body in list_files(): 
    if fn.endswith('.txt'): 
     print body() 

đây, list_files trả về một loạt các tên tập tin và một "thunk" (lambda không có đối số) trả về nội dung của tập tin. "Thunk" là một đánh giá hoãn lại. Sử dụng thunks cho phép bạn tách mối quan tâm của bạn:

  • Vòng lặp for không cần phải biết làm thế nào để đọc file, vì vậy list_files có thể được thay thế bằng list_ftp_files hoặc list_zip_archive.
  • Chức năng list_files không cần biết tệp nào sẽ được đọc. Với thunks, nó không phải đọc từng tập tin.

Trong đánh giá thích hợp, một khi bạn đánh giá "thunk", nó sẽ tự thay thế bằng bản sao được đánh giá, vì vậy việc đánh giá nó hai lần sẽ không hoạt động nhiều hơn việc đánh giá nó một lần. Có nhiều cách khác để thực hiện điều tương tự, chẳng hạn như với các lớp và đối tượng có giá trị bộ nhớ cache.

Đánh giá chậm là một thành ngữ (tương đối) phổ biến trong Đề án. Trong Haskell, các đánh giá được hoãn lại theo mặc định và bạn không cần bất kỳ cú pháp nào để thực hiện nó (có cú pháp đặc biệt để tắt nó).

+4

Lambda được hoãn lại, nhưng phải cẩn thận về lưu trữ, vì họ không nắm bắt được fn như bạn đang có họ: http://codepad.org/fXfIj364. Và một thông báo khác: http://codepad.org/poXS7nc2. –

+0

Đó là một điểm tốt, và một trong những lý do tôi tránh xa lambda khi viết mã bằng Python. –

+1

Đây là lý do tại sao tôi thích các hàm nội tuyến + 'functools.partial' để cố định đối số: http: // codepad.org/fwxLbl7l – schlamar