Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #33403

Re: Lazy Attribute

References <DUB117-W881D7D74D529D159D8B33F91520@phx.gbl>
From Ian Kelly <ian.g.kelly@gmail.com>
Date 2012-11-15 15:46 -0700
Subject Re: Lazy Attribute
Newsgroups comp.lang.python
Message-ID <mailman.3729.1353019611.27098.python-list@python.org> (permalink)

Show all headers | View raw


On Thu, Nov 15, 2012 at 12:33 PM, Andriy Kornatskyy
<andriy.kornatskyy@live.com> wrote:
>
> A lazy attribute is an attribute that is calculated on demand and only once.
>
> The post below shows how you can use lazy attribute in your Python class:
>
> http://mindref.blogspot.com/2012/11/python-lazy-attribute.html
>
> Comments or suggestions are welcome.

I should add that I like the approach you're taking here.  Usually
when I want a lazy property I just make an ordinary property of a
memoized function call:

def memoize(func):
    cache = {}
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        kwset = frozenset(kwargs.items())
        try:
            return cache[args, kwset]
        except KeyError:
            result = cache[args, kwset] = func(*args, **kwargs)
            return result
    return wrapper

class Foo:
    def __init__(self):
        self.times_called = 0

    @property
    @memoize   # Alternatively, use functools.lru_cache
    def forty_two(self):
        self.times_called += 1
        return 6 * 9


>>> foo = Foo()
>>> foo.times_called
0
>>> foo.forty_two
54
>>> foo.times_called
1
>>> foo.forty_two
54
>>> foo.times_called
1


Although you don't go into it in the blog entry, what I like about
your approach of replacing the descriptor with an attribute is that,
in addition to being faster, it makes it easy to force the object to
lazily reevaluate the attribute, just by deleting it.  Using the
Person example from your blog post:

>>> p = Person('John', 'Smith')
>>> p.display_name
'John Smith'
>>> p.display_name
'John Smith'
>>> p.calls_count
1
>>> p.first_name = 'Eliza'
>>> del p.display_name
>>> p.display_name
'Eliza Smith'
>>> p.calls_count
2

Although in general it's probably better to use some form of reactive
programming for that.

Back to comp.lang.python | Previous | NextNext in thread | Find similar | Unroll thread


Thread

Re: Lazy Attribute Ian Kelly <ian.g.kelly@gmail.com> - 2012-11-15 15:46 -0700
  Re: Lazy Attribute Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2012-11-16 10:29 +0000
    Re: Lazy Attribute "Stefan H. Holek" <stefan@epy.co.at> - 2012-11-16 11:45 +0100
    RE: Lazy Attribute Andriy Kornatskyy <andriy.kornatskyy@live.com> - 2012-11-16 13:46 +0300
    Re: Lazy Attribute "Stefan H. Holek" <stefan@epy.co.at> - 2012-11-16 13:46 +0100

csiph-web