Equivalent to Python Scala lazy val

I'm currently trying to port some Scala code to a Python project, and I came across the following bit of Scala code:

lazy val numNonZero = weights.filter { case (k,w) => w > 0 }.keys 

weights is a really long list of tuples of elements and their associated probability weighting. Elements are often added and removed from this list, but checking how many elements have a nonzero probability is relatively rare. There are several other rare, but expensive operations, like this one in the code that I am porting, which seems to be very beneficial from using lazy val . What is the most idiomatic way of Python to do something similar to Scala lazy val ?

+4
source share
3 answers

generator expression

 >>> weights = [(1,2), (2,0), (3, 1)] >>> numNonZero = (k for k, w in weights if w > 0) >>> next(numNonZero) 1 >>> next(numNonZero) 3 >>> next(numNonZero) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration >>> next(numNonZero, -1) -1 

 >>> numNonZero = (k for k, w in weights if w > 0) >>> for k in numNonZero: ... print(k) ... 1 3 

Python Tutorial: Generator Expressions

+2
source

In Scala, lazy val is a final variable that is evaluated once at the time of its first access, and not at the time of its declaration. This is essentially a memoized function with no arguments. Here is one of the ways you can implement memoization decorator in Python:

 from functools import wraps def memoize(f): @wraps(f) def memoized(*args, **kwargs): key = (args, tuple(sorted(kwargs.items()))) # make args hashable result = memoized._cache.get(key, None) if result is None: result = f(*args, **kwargs) memoized._cache[key] = result return result memoized._cache = {} return memoized 

Here's how to use it. With property you can even remove empty parentheses like Scala:

 >>> class Foo: ... @property ... @memoize ... def my_lazy_val(self): ... print "calculating" ... return "some expensive value" >>> a = Foo() >>> a.my_lazy_val calculating 'some expensive value' >>> a.my_lazy_val 'some expensive value' 
+6
source

Essentially, you want to change the way you access attributes for numNonZero . Python does this with descriptor . In particular, take a look at their app on Properties .

In this case, you can postpone the calculation until access to the attribute is reached, caching it for later use.

+3
source

Source: https://habr.com/ru/post/1496098/


All Articles