What's better about Ruby than Python?

Alex Martelli aleax at aleax.it
Thu Aug 21 05:20:27 EDT 2003


Andrew Dalke wrote:

> Alex:
>> You could use a class if its instances where descriptors, i.e.
>> supported __get__ appropriately ... See Raymond Hettinger's
>> HOWTO on descriptors -- a *wonderful* treatment of the subject.
> 
> I'm slowing easing my way into this new stuff.  I read it through
> once, but it didn't all sink in.  Could you post an example of how
> to use it for my cache example?

You posted...:

>>> import time
>>> def CachedCall(f):
...    cache = {}
...    def cached_call(self, *args):
...       if args in cache:
...          return cache[args]
...       x = f(self, *args)
...       cache[args] = x
...       return x
...    return cached_call
...
>>> class LongWait:
...    def compute(self, i):
...       time.sleep(i)
...       return i*2
...    compute = CachedCall(compute)

To use descriptors, you should first of all change LongWait to
be new-style, i.e. change its header to "class LongWait(object):".
Not strictly necessary, but might avoid some minor issues.

Thenm, something like...:

>>> class CachedCall(object):
...   def __init__(self, f):
...     self.f = f
...     self.cache = {}
...   def cached_call(self, *args):
...     if args in self.cache: return self.cache[args]
...     x = self.f(self.obj, *args)
...     self.cache[args] = x
...     return x
...   def __get__(self, obj, cls):
...     self.obj = obj
...     return self.cached_call
...

should closely mimic your semantics, including ignoring
what I call obj and you call self in determining whether
a certain set of argumens is cached.  Haven't tested it,
mind you, but this is the general concept.  Having obj
(or self) be relevant may be obtained by keeping the
cache right on obj (or self) [unless __slots__ should
interfere, in which case you might try workarounds...].


Alex





More information about the Python-list mailing list