2016-09-06 19 views
5

Tôi đang viết một kịch bản trong đó tôi phải kiểm tra các con số dựa trên một số điều kiện. Nếu bất kỳ điều kiện nào được đáp ứng tôi muốn trả lại True và tôi muốn làm điều đó một cách nhanh nhất có thể.Có bất kỳ() nào được đánh giá uể oải không?

Ý tưởng đầu tiên của tôi là sử dụng any() thay vì tuyên bố lồng nhau if hoặc nhiều or liên kết các điều kiện của tôi. Vì tôi sẽ hài lòng nếu bất kỳ điều kiện nào là True tôi thực sự có thể hưởng lợi từ việc any() trở nên lười biếng và quay trở lại Đúng ngay khi có thể.

Dựa trên thực tế là các bản in sau xảy ra ngay lập tức và không sau 10 (= 0 + 1 + 2 + 3 + 4) giây tôi giả sử nó là. Đó là trường hợp hoặc tôi bằng cách nào đó nhầm lẫn?

import time 

def some(sec): 
    time.sleep(sec) 
    return True 

print(any(some(x) for x in range(5))) 
+4

Có - nó lười ... –

+0

cảm ơn! Có cùng, giữ cho 'all()' tôi tưởng tượng –

+0

Vâng, đúng ... –

Trả lời

12

Vâng, any()all() ngắn mạch, hủy ngay sau khi kết quả là rõ ràng: Xem docs:

tất cả (iterable)

Return True nếu tất cả các yếu tố của iterable là true (hoặc nếu iterable là trống). Tương đương với:

def all(iterable): 
    for element in iterable: 
     if not element: 
      return False 
    return True 

bất kỳ (iterable)

Return True nếu bất kỳ yếu tố của iterable là đúng. Nếu có thể lặp lại là trống, hãy trả về Sai. Tương đương với:

def any(iterable): 
    for element in iterable: 
     if element: 
      return True 
    return False 
+1

tôi thường tìm thấy các tài liệu xấu, nhưng trong trường hợp này nó là vượt quá rõ ràng. Cảm ơn rất nhiều! Đây cũng chính xác là những gì tôi đã có trong tâm trí về _lazy evaluation_. làm thế nào là _short-circuiting_ bất kỳ khác nhau? –

+1

Biểu thức máy phát điện là lười biếng theo nghĩa là nó chỉ gọi 'một số (x)' khi mục tiếp theo được yêu cầu. 'short/all' ngắn mạch theo nghĩa là nó sẽ chỉ yêu cầu các mục cho đến khi kết quả là rõ ràng. Bạn có thể nói rằng 'bất kỳ ([một số (x) cho x trong phạm vi (5)])' vẫn ngắn mạch, nhưng không phải là lười vì danh sách hiểu kết quả trong 'some' được gọi trên tất cả các phần tử của' range (x) 'trước' bất kỳ' bắt đầu, nhưng 'bất kỳ' sẽ vẫn dừng kiểm tra danh sách đầu vào càng sớm càng tốt. – chepner

4

Trong khi all()any() chức năng ngắn mạch trên phần tử đầu tiên "true" của một iterable, các iterable chính nó có thể được xây dựng theo một cách không lười biếng. Hãy xem xét ví dụ này:

>> any(x == 100 for x in range(10**8)) 
True 

Sẽ mất vài giây để thực thi trong Python 2 là range(10**8) tạo danh sách 10 ** 8 phần tử. Biểu thức tương tự chạy ngay lập tức trong Python 3, trong đó range() là lười.

+1

Quan sát tốt –

+0

Tôi thấy điều này khó hiểu bởi vì tôi biết rằng 'range()' tạo danh sách đầy đủ trong python2, nhưng sau đó bạn quấn nó trong một trình tạo, vốn là lười biếng –

+0

@Chris_Rands: Khi bạn sử dụng biểu thức * generator *, trong ví dụ trên, biểu thức 'for' được đánh giá ngay lập tức. Do đó, 'range()' xây dựng một danh sách đầy đủ ngay cả trước khi bộ tạo được chạy. –

2

Có, đó là lười biếng như chứng minh bằng cách như sau:

def some(x, result=True): 
    print(x) 
    return result 

>>> print(any(some(x) for x in range(5))) 
0 
True 

>>> print(any(some(x, False) for x in range(5))) 
0 
1 
2 
3 
4 
False 

Trong chạy đầu tiên any() dừng lại sau khi kiểm tra mục đầu tiên, tức là nó ngắn mạch đánh giá.

Trong lần chạy thứ hai, any() tiếp tục kiểm tra cho đến khi chuỗi hết hạn.

2

Vâng, và đây là một thử nghiệm cho thấy nó thậm chí nhiều hơn dứt khoát hơn thí nghiệm thời gian của bạn:

import random 

def some(x): 
    print(x, end = ', ') 
    return random.random() < 0.25 

for i in range(5): 
    print(any(some(x) for x in range(10))) 

điển hình chạy:

0, 1, 2, True 
0, 1, True 
0, True 
0, 1, 2, 3, True 
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, False 
3

Như Tim đã nói một cách chính xác, anyall làm ngắn mạch, nhưng trong mã của bạn, những gì làm cho nó lười biếng là việc sử dụng generators. Ví dụ, đoạn mã sau sẽ không được lười biếng:

print(any([slow_operation(x) for x in big_list])) 

Danh sách này sẽ được xây dựng hoàn chỉnh và tính toán, và chỉ sau đó thông qua như là một cuộc tranh cãi để any.

Máy phát điện, mặt khác, là vòng lặp có thể tính toán từng mục theo yêu cầu. Chúng có thể là expressions, functions hoặc đôi khi được triển khai theo cách thủ công là lười biếng iterators.

+0

đẹp. Cảm ơn! –

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