Lazy score in Python

What is a lazy score in Python?

One site said:

In Python 3.x, the range() function returns a special range object that evaluates list items upon request (deferred or deferred evaluation):

 >>> r = range(10) >>> print(r) range(0, 10) >>> print(r[3]) 3 

What is meant by this?

+38
python lazy-evaluation
Dec 12 '13 at 4:55
source share
4 answers

The object returned by range() (or xrange() in Python2.x) is called generator .

Instead of storing the entire range [0,1,2,..,9] in memory, the generator stores the definition for (i=0; i<10; i+=1) and calculates the next value only when necessary (AKA lazy-evaluation )

Essentially, a generator allows you to return a list as a structure, but here are some differences:

  • The list saves all items when it is created. The generator generates the next element when necessary.
  • The list can be repeated as necessary, the generator can be repeated only once.
  • A list can receive elements by index, a generator cannot - it only generates values ​​once, from beginning to end.

A generator can be created in two ways:

(1) Very similar to a list comprehension:

 # 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) As a function, using yield to return the following value:

 # 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) 

Note: Even if range(5000000) is a generator in Python3.x, [x/2 for x in range(5000000)] is still a list. range(...) does the job and generates x one at a time, but the entire list of x/2 values ​​will be computed when this list is created.

+59
Dec 12 '13 at 4:58
source share

In short, lazy evaluation means that the object is evaluated when necessary, and not when it is created.

In Python 2, a range will return a list - this means that if you give it a large amount, it will calculate the range and return at creation time:

 >>> i = range(100) >>> type(i) <type 'list'> 

In Python 3, however, you get a special range object:

 >>> i = range(100) >>> type(i) <class 'range'> 

Only when you consume it will it be actually appreciated - in other words, it will only return numbers in the range when you really need them.

+12
Dec 12 '13 at 5:02
source share

A Github repository called Python Patterns and Wikipedia tell us what a lazy rating is.

Delays the calculation of expr until its value is needed, and avoids repeated evals.

range in python3 is not a total lazy estimate because it does not avoid re-evaluating eval.

A more classic example for lazy computing is 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 (aka lazy_property) is a decorator that converts a function into a property of deferred evaluation. The first time the property is accessed, the function is called to get the result, and then the value is used the next time the property is accessed.

eg:

 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) 

To use the correct word, a python generator object such as range looks more like a call_by_need pattern, rather than a lazy rating

+2
Jan 24 '18 at 6:26
source share

Evaluating lazy Python 3 variables with @functools.lru_cache

For Google users who want to do lazy evaluation of variables in Python, visit https://docs.python.org/3.7/library/functools.html#functools.lru_cache

Example from the docs:

 @lru_cache(maxsize=None) def fib(n): if n < 2: return n return fib(n-1) + fib(n-2) >>> [fib(n) for n in range(16)] [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610] >>> fib.cache_info() CacheInfo(hits=28, misses=16, maxsize=None, currsize=16) 

See Also: Is there a decorator for easy caching of function return values?

0
May 12 '19 at 9:20
source share



All Articles