Nếu tôi làm:Liệu ngắn mạch giảm() của Python?
result = reduce(operator.and_, [False] * 1000)
Nó sẽ dừng sau kết quả đầu tiên? (Kể từ False & anything == False
)
Tương tự:
result = reduce(operator.or_, [True] * 1000)
Nếu tôi làm:Liệu ngắn mạch giảm() của Python?
result = reduce(operator.and_, [False] * 1000)
Nó sẽ dừng sau kết quả đầu tiên? (Kể từ False & anything == False
)
Tương tự:
result = reduce(operator.or_, [True] * 1000)
Nó không. Lựa chọn thay thế của bạn trong trường hợp này là any và all.
result = reduce(operator.and_, [False] * 1000)
result = reduce(operator.or_, [True] * 1000)
có thể được thay thế bằng
result = all([False] * 1000)
result = any([True] * 1000)
mà làm ngắn mạch.
Kết quả thời gian hiển thị sự khác biệt:
In [1]: import operator
In [2]: timeit result = reduce(operator.and_, [False] * 1000)
10000 loops, best of 3: 113 us per loop
In [3]: timeit result = all([False] * 1000)
100000 loops, best of 3: 5.59 us per loop
In [4]: timeit result = reduce(operator.or_, [True] * 1000)
10000 loops, best of 3: 113 us per loop
In [5]: timeit result = any([True] * 1000)
100000 loops, best of 3: 5.49 us per loop
Không chỉ giảm() không ngắn mạch, nó có thể không thể ngắn mạch trên tất cả các mặt hàng được giảm, bởi vì nó chỉ xem xét các mục hai tại một thời gian. Ngoài ra, nó không có ý tưởng về các điều kiện theo đó chức năng được sử dụng ngắn mạch. (Sẽ rất tiện lợi nếu các hàm có thể có một thuộc tính cho biết giá trị mà tại đó chúng bắt đầu đoản mạch, mà giảm() sau đó có thể nhận ra và sử dụng, nhưng không.)
Đây là lý do tại sao người dùng Lisp yêu Lisp rất nhiều - bởi vì tất cả các chức năng đều là dữ liệu, đó là (chính) có thể thực hiện loại phát hiện này. – Lucretiel
Nó cũng có thể là có thể (xem fate of reduce) rằng việc thay thế sẽ giảm bớt việc thực hiện sẽ hoạt động tốt.
Ý tưởng này đã làm việc hoàn hảo để tôi làm cho mọi thứ minh bạch hơn trong thiết kế.
def ipairs(seq):
prev = None
for item in seq:
if prev is not None:
yield (prev, item)
prev = item
def iapply(seq, func):
for a, b in ipairs(seq):
yield func(a, b)
def satisfy(seq, cond):
return all(iapply(seq, cond))
def is_uniform(seq):
return satisfy(seq, lambda a, b: a == b)
Như bạn thấy giảm được chia thành iapply <-ipairs.
Xin lưu ý nó không phải là tương đương với
def ireduce(seq, func):
prev = None
for item in seq:
if prev is None:
prev = item
else:
prev = func(prev, item)
return prev
Gấu nhớ rằng đánh giá ngắn mạch không phải lúc nào những gì bạn muốn. "Sửa chữa" giảm ngắn mạch sẽ là một sai lầm vì lý do đó. Ví dụ, gần đây tôi đã phải thay đổi việc sử dụng all() để giảm() trong khi xử lý danh sách biểu mẫu trong django: Tôi muốn báo cáo bất kỳ vấn đề nào is_valid(), không chỉ là vấn đề đầu tiên.
nó có thể sử dụng một đối số từ khóa cho các tiêu chí ngắn mạch, các nội trang khác làm: giảm (operator.or, mylist, key = lambda x:: x <0) – LBarret
Bạn nói đúng. 'any()' và 'all()' dường như chính xác những gì tôi cần (và có thể rõ ràng hơn). Làm thế nào bạn làm điều đó thời gian? –
Tôi đang sử dụng lệnh 'ipython' và lệnh' timeit' của nó. Nhưng Python có một mô-đun timeit. Vì vậy, bạn có thể làm 'python -mtimeit" result = any ([True] * 10) "' từ dòng lệnh cho thời gian. –