什麼是python中的懶惰評價?懶惰評價python
一個網站上說:
在Python 3.x中範圍()函數返回其計算需求(懶惰或推遲評估)列表的元素一個特殊的範圍對象:
>>> r = range(10)
>>> print(r)
range(0, 10)
>>> print(r[3])
3
什麼是這個意思嗎?
什麼是python中的懶惰評價?懶惰評價python
一個網站上說:
在Python 3.x中範圍()函數返回其計算需求(懶惰或推遲評估)列表的元素一個特殊的範圍對象:
>>> r = range(10)
>>> print(r)
range(0, 10)
>>> print(r[3])
3
什麼是這個意思嗎?
range()
(或Python2.x中的xrange()
)返回的對象被稱爲generator。
生成器不會將整個範圍[0,1,2,..,9]
存儲在內存中,而是存儲(i=0; i<10; i+=1)
的定義,並僅在需要時計算下一個值(AKA懶惰評估)。
從本質上講,一臺發電機允許返回狀結構的列表,但這裏有一些差異:
(1)非常相似,列表理解:
# this is a list, create all 5000000 x/2 values immediately, uses []
lis = [x/2 for x in range(5000000)]
# this is a generator, creates each x/2 value only when it is needed, uses()
gen = (x/2 for x in range(5000000))
(2)作爲一個功能,採用yield
返回
的發電機可以用兩種方法來創建下一個值:
# this is also a generator, it will run until a yield occurs, and return that result.
# on the next call it picks up where it left off and continues until a yield occurs...
def divby2(n):
num = 0
while num < n:
yield num/2
num += 1
# same as (x/2 for x in range(5000000))
print divby2(5000000)
注意:儘管range(5000000)
是Python3.x中的生成器,但[x/2 for x in range(5000000)]
仍然是一個列表。 range(...)
它的工作是否正常並且每次生成一個x
,但是在創建此列表時將計算整個x/2
值的列表。
這是一個很好的詳細答案,bcorso。 :) +1 – zx81
實際上,'range'(或2.x中的'xrange')不會*返回一個生成器。一個生成器是一個迭代器 - 對於任何生成器'g'你都可以調用'next(g)'。範圍對象實際上是可迭代的。你可以調用'iter'來得到一個迭代器,但它本身不是一個迭代器(你不能調用'next')。除此之外,這意味着您可以多次迭代單個範圍對象。 –
簡而言之,懶惰評估意味着對象在需要時進行評估,而不是在創建時進行評估。
在Python 2,範圍將返回一個列表 - 這意味着,如果你給它一個大的數字,它會計算的範圍,並在創建的時候返回:但是
>>> i = range(100)
>>> type(i)
<type 'list'>
在Python 3,你會得到一個特殊的範圍對象:
>>> i = range(100)
>>> type(i)
<class 'range'>
只有當你使用它,將它實際上進行評估 - 換句話說,它只會在返回範圍內的數字,當你真正需要它們。
感謝您定義「懶惰」:) – BoltzmannBrain
一個名爲python patterns和wikipedia的github回購告訴我們什麼是懶惰評估。
推遲expr的eval直到它的值被需要,並避免重複的evals。
range
python3不是一個完整的懶惰評估,因爲它不能避免重複評估。
更典型的例子爲惰性計算是cached_property
:
import functools
class cached_property(object):
def __init__(self, function):
self.function = function
functools.update_wrapper(self, function)
def __get__(self, obj, type_):
if obj is None:
return self
val = self.function(obj)
obj.__dict__[self.function.__name__] = val
return val
的cached_property(a.k.a lazy_property)是轉換FUNC成惰性計算特性的裝飾。第一次訪問屬性時,調用func來獲取結果,然後在下次訪問屬性時使用該值。
例如:
class LogHandler:
def __init__(self, file_path):
self.file_path = file_path
@cached_property
def load_log_file(self):
with open(self.file_path) as f:
# the file is to big that I have to cost 2s to read all file
return f.read()
log_handler = LogHandler('./sys.log')
# only the first time call will cost 2s.
print(log_handler.load_log_file)
# return value is cached to the log_handler obj.
print(log_handler.load_log_file)
要使用適當的字,一個python發生器對象像範圍更像通過設計call_by_need圖案,而不是惰性計算
創建一個發生器(例如包含'yield'的'def'),它會在產生一個值之前產生像print一樣的副作用。然後循環發生器,每次迭代延遲一秒。印刷何時發生? Python 3的'range'(很像Python 2中的'xrange')的工作方式就像這樣:計算直到問題才完成。這就是「懶惰評價」的意思。 – user2864740