Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

lazy evaluation of a variable

495 views
Skip to first unread message

Gelonida N

unread,
Jun 17, 2012, 5:35:12 PM6/17/12
to pytho...@python.org
Hi,

I'm not sure whether what I ask for is impossible, but would know how
others handle such situations.



I'm having a module, which should lazily evaluate one of it's variables.
Meaning that it is evaluated only if anybody tries to use this variable.

At the moment I don't know how to do this and do therefore following:


####### mymodule.py #######
var = None

def get_var():
global var
if var is not None:
return var
var = something_time_consuming()



Now the importing code would look like

import mymodule
def f():
var = mymodule.get_var()

The disadvantage is, that I had to change existing code directly
accessing the variable.


I wondered if there were any way to change mymodule.py such, that the
importing code could just access a variable and the lazy evaluation
would happen transparently.

import mymodule
def f():
var = mymodule.var



Thanks in advance for you suggestions





Cameron Simpson

unread,
Jun 17, 2012, 5:44:47 PM6/17/12
to pytho...@python.org
On 17Jun2012 23:35, Gelonida N <gelo...@gmail.com> wrote:
| I'm having a module, which should lazily evaluate one of it's variables.
| Meaning that it is evaluated only if anybody tries to use this variable.

If it were an object member you could use a property.
Does it need to be a module global?

In related news, can one make "properties" for modules? I was wondering
about this a month or so ago.
--
Cameron Simpson <c...@zip.com.au>

If your new theorem can be stated with great simplicity, then there
will exist a pathological exception. - Adrian Mathesis

Steven D'Aprano

unread,
Jun 17, 2012, 7:01:03 PM6/17/12
to
On Mon, 18 Jun 2012 07:44:47 +1000, Cameron Simpson wrote:

> On 17Jun2012 23:35, Gelonida N <gelo...@gmail.com> wrote: | I'm having
> a module, which should lazily evaluate one of it's variables. | Meaning
> that it is evaluated only if anybody tries to use this variable.
>
> If it were an object member you could use a property. Does it need to be
> a module global?
>
> In related news, can one make "properties" for modules? I was wondering
> about this a month or so ago.


There have been various half-hearted requests for such a feature,
including by myself, but nothing concrete.

One day, in my Copious Spare Time, I intend to write a proper feature
request and/or PEP for such a feature. Obviously the absolute earliest
such a feature could be introduced is Python 3.4, about 18 months from
now. (Although frankly, I would imagine significant opposition from the
more conservative Python developers.)


--
Steven

Peter Otten

unread,
Jun 17, 2012, 7:40:57 PM6/17/12
to pytho...@python.org
Gelonida N wrote:

> I'm having a module, which should lazily evaluate one of it's variables.
> Meaning that it is evaluated only if anybody tries to use this variable.
>
> At the moment I don't know how to do this and do therefore following:
>
>
> ####### mymodule.py #######
> var = None
>
> def get_var():
> global var
> if var is not None:
> return var
> var = something_time_consuming()
>
>
>
> Now the importing code would look like
>
> import mymodule
> def f():
> var = mymodule.get_var()
>
> The disadvantage is, that I had to change existing code directly
> accessing the variable.
>
>
> I wondered if there were any way to change mymodule.py such, that the
> importing code could just access a variable and the lazy evaluation
> would happen transparently.
>
> import mymodule
> def f():
> var = mymodule.var
>
>
>
> Thanks in advance for you suggestions

You can inject arbitrary objects into sys.modules:

>>> import sys
>>> class MyModule(object):
... def __init__(self):
... self._var = None
... @property
... def var(self):
... result = self._var
... if result is None:
... print "calculating..."
... self._var = result = 42
... return result
...
>>> sys.modules["mymodule"] = MyModule()
>>> import mymodule
>>> mymodule.var
calculating...
42
>>> mymodule.var
42


Terry Reedy

unread,
Jun 18, 2012, 2:40:03 AM6/18/12
to pytho...@python.org
On 6/17/2012 5:35 PM, Gelonida N wrote:

> I'm having a module, which should lazily evaluate one of it's variables.

If you literally mean a module object, that is not possible. On the
other hand, it is easy to do with class instances, via the __getattr__
special method or via properties.

> At the moment I don't know how to do this and do therefore following:
> ####### mymodule.py #######
> var = None
>
> def get_var():
> global var
> if var is not None:
> return var
> var = something_time_consuming()

> Now the importing code would look like
>
> import mymodule
> def f():
> var = mymodule.get_var()
>
> The disadvantage is, that I had to change existing code directly
> accessing the variable.

> I wondered if there were any way to change mymodule.py such, that the
> importing code could just access a variable and the lazy evaluation
> would happen transparently.
>
> import mymodule
> def f():
> var = mymodule.var

You could now do (untested, too late at night)
# mymodule.py
class _Lazy():
def __getattr__(self, name):
if name == 'var':
self.var = something_time_consuming()
return self.var

lazy = _Lazy()

# user script
from mymodule import lazy
def f():
var = lazy.var

See Peter's post for using properties instead. That probably scales
better for multiple lazy attibutes.

--
Terry Jan Reedy



Gelonida N

unread,
Jun 18, 2012, 7:16:58 PM6/18/12
to pytho...@python.org
On 06/17/2012 11:35 PM, Gelonida N wrote:
> Hi,
>
> I'm not sure whether what I ask for is impossible, but would know how
> others handle such situations.
>
>
>
> I'm having a module, which should lazily evaluate one of it's variables.
> Meaning that it is evaluated only if anybody tries to use this variable.
>
> At the moment I don't know how to do this and do therefore following:
>
>
> ####### mymodule.py #######
> var = None
>
> def get_var():
> global var
> if var is not None:
> return var
> var = something_time_consuming()
>
>
>
> Now the importing code would look like
>
> import mymodule
> def f():
> var = mymodule.get_var()
>
> The disadvantage is, that I had to change existing code directly
> accessing the variable.
>
>
> I wondered if there were any way to change mymodule.py such, that the
> importing code could just access a variable and the lazy evaluation
> would happen transparently.
>
> import mymodule
> def f():
> var = mymodule.var
>
Thanks everybody for your responses. This gave me quite some ideas.

It seems, that none of the solutions would allow to have the changes
only in the module.

More out of curiosity than out of real necessity I wanted to know,
whether it would be possible to hide the lazy evaluation from already
existing code, that has already the import statement written.
So the question basically boiled down to
"can one make 'properties' for modules?"

It seems no.
Probably there aren't many real use cases except for monkey patching
libraries or for logging accesses to a module's variable


rantingri...@gmail.com

unread,
Jun 19, 2012, 12:05:50 AM6/19/12
to
On Sunday, June 17, 2012 6:01:03 PM UTC-5, Steven D&#39;Aprano wrote:

> One day, in my Copious Spare Time, I intend to write a proper feature
> request and/or PEP for such a feature. Obviously the absolute earliest
> such a feature could be introduced is Python 3.4, about 18 months from
> now. (Although frankly, I would imagine significant opposition from the
> more conservative Python developers.)

Well these conservatives must have been suffering from chronic mononucleosis because i have never heard a peep from them! I wish they would "grow a pair" and speak up a bit more often because the language would benefit greatly from some austerity measures, strong leadership, and most of all; some Gawd damned consistency!
0 new messages