What's better about Ruby than Python?
Kenny Tilton
ktilton at nyc.rr.com
Thu Aug 21 11:59:26 EDT 2003
Alex Martelli wrote:
> Andrew Dalke wrote:
>
>
>>Alex Martell:
>>
>>>... def __get__(self, obj, cls):
>>>... self.obj = obj
>>>... return self.cached_call
>>
>>That's the part where I still lack understanding.
>>
>>class Spam:
>> def f(self):
>> pass
>> f = CachedCall(f)
>
>
> That's an oldstyle class -- use a newstyle one for smoothest
> and most reliable behavior of descriptors
>
>
>>obj = Spam()
>>obj.f()
>>
>>Under old-style Python
>> obj.f is the same as getattr(obj, "f")
>
>
> This equivalence holds today as well -- the getattr
> builtin has identical semantics to direct member access.
>
>
>> which fails to find 'f' in the instance __dict__
>> so looks for 'f' in the class, and finds it
>> This is not a Python function, so it does not
>> get bound to self. It's simply returned.
>>
>> obj.f() takes that object and calls it. In my original
>> code (not shown) I tried implementing a __call__
>> which did get called, but without the instance self.
>
>
> Sure.
>
>
>>Under new-style Python
>> obj.f is the same as getattr(obj, "f")
>
>
> Yes.
>
>
>> which fails to find 'f' in the instance __dict__ so
>> looks for 'f' in the class, and finds the CachedCall.
>
>
> Sure.
>
>
>> Python checks if the object implements __get__,
>> in which case it's called a descriptor. If so, it's
>
>
> Exactly.
>
>
>> called with the 'obj' as the first parameter. The
>> return value of this call is used as the value for
>> the attribute.
>>
>>Is that right?
>
>
> Yes! So what is it that you say you don't get?
>
>
>
>>>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.
>>
>>Why should obj make a difference? There's only
>>one CachedCall per method per .... Ahh, because it's
>>in the class def, not the instance. Adding support for
>>that using a weak dict is easy.
>
>
> If obj is such that it can be used as a key into a dict
> (weak or otherwise), sure. Many class instances of some
> interest can't -- and if they can you may not like the
> result. COnsider e.g.
>
> class Justanyclass:
> def __init__(self, x): self.x = x
> def compute(self, y): return self.x + y
>
> pretty dangerous to cache THIS compute method -- because,
> as a good instance method should!, it depends crucially
> on the STATE of the specific instance you call it on.
>
>
>
>>Yeah, and my approach won't work with kwargs nor any
>>other unhashable element. Since I didn't know what the
>>Lisp code did nor how Lisp handles unhashable elements,
>>I decided just to implement the essential idea.
>
>
> An automatically cachable method on general objects is
> quite tricky.
Lisp hashtables can key off any Lisp datum, but...
> I don't think the Lisp code did anything
> to deal with that trickiness,
No, it did not. That snippet was from a toy (and incomplete)
implementation of my more elaborate Cells package. the toy was developed
over the keyboard during a talk I gave on Sunday. The next step would
have been to determine when the closure had best re-execute the code
body to see if the world had changed in interesting ways, but that is a
big step and requires dependency tracking between cells.
Once a Cell is told an input has changed, it re-runs its body to see if
it comes up with a different result, in which case it caches that and
tells other dependents to rethink their caches.
So what is shown in my example is fun but halfbaked. I was just trying
to show how a macro could hide the plumbing of an interesting mechanism
so the reader can focus on the essence.
--
kenny tilton
clinisys, inc
http://www.tilton-technology.com/
---------------------------------------------------------------
"Career highlights? I had two. I got an intentional walk from
Sandy Koufax and I got out of a rundown against the Mets."
-- Bob Uecker
More information about the Python-list
mailing list