From: Lie Ryan on
On 03/17/2010 04:32 PM, Steven D'Aprano wrote:
> On Wed, 17 Mar 2010 15:57:17 +1100, Lie Ryan wrote:
>
>> Most people probably would never need to use
>> descriptor protocol directly, since the immediate benefit of descriptor
>> protocol are property(), classmethod(), and instancemethod() decorators
>> which, without descriptor protocol, would never become a possibility.
>
>
> There's an instancemethod decorator? Where?
>
> Are you thinking of staticmethod? "instancemethod", if you mean what I
> think you mean, doesn't need a decorator because it is the default
> behaviour for new-style classes.

Whoops... yep, sorry about that. Got all it up the mixed head in...
From: Lie Ryan on
On 03/17/2010 08:12 PM, Bruno Desthuilliers wrote:
> Patrick Maupin a �crit :
>> On Mar 16, 1:59 pm, Jason Tackaberry <t...(a)urandom.ca> wrote:
>>> Why not create the bound methods at instantiation time, rather than
>>> using the descriptor protocol which has the overhead of creating a new
>>> bound method each time the method attribute is accessed?
>>
>> Well, for one thing, Python classes are open. They can be added to at
>> any time. For another thing, you might not ever use most of the
>> methods of an instance, so it would be a huge waste to create those.
>
> A possible optimization would be a simple memoization on first access.

But what if, for example, one uses some descriptor/metaclass magic to
make it so that each subsequent access to the attribute returns a method
bound to different objects?
From: Patrick Maupin on
On Mar 17, 4:12 am, Bruno Desthuilliers <bruno.
42.desthuilli...(a)websiteburo.invalid> wrote:
> Patrick Maupin a écrit :
>
> > On Mar 16, 1:59 pm, Jason Tackaberry <t...(a)urandom.ca> wrote:
> >> Why not create the bound methods at instantiation time, rather than
> >> using the descriptor protocol which has the overhead of creating a new
> >> bound method each time the method attribute is accessed?
>
> > Well, for one thing, Python classes are open.  They can be added to at
> > any time.  For another thing, you might not ever use most of the
> > methods of an instance, so it would be a huge waste to create those.
>
> A possible optimization would be a simple memoization on first access.

I do agree that memoization on access is a good pattern, and I use it
frequently. I don't know if I would want the interpreter
automagically doing that for everything, though -- it would require
some thought to figure out what the overhead cost is for the things
that are only used once.

Usually, I will have a slight naming difference for the things I want
memoized, to get the memoization code to run. For example, if you add
an underbar in front of everything you want memoized:

class foo(object):

def _bar(self):
pass

def __getattr__(self, aname):
if aname.startswith('_'):
raise AttributeError
value = getattr(self, '_' + aname)
self.aname = value
return value

obj = foo()

So then the first time you look up obj.bar, it builds the bound
method, and on subsequent accesses it just returns the previously
bound method.

Regards,
Pat
From: Bruno Desthuilliers on
Lie Ryan a �crit :
> On 03/17/2010 08:12 PM, Bruno Desthuilliers wrote:
>> Patrick Maupin a �crit :
>>> On Mar 16, 1:59 pm, Jason Tackaberry <t...(a)urandom.ca> wrote:
>>>> Why not create the bound methods at instantiation time, rather than
>>>> using the descriptor protocol which has the overhead of creating a new
>>>> bound method each time the method attribute is accessed?
>>> Well, for one thing, Python classes are open. They can be added to at
>>> any time. For another thing, you might not ever use most of the
>>> methods of an instance, so it would be a huge waste to create those.
>> A possible optimization would be a simple memoization on first access.
>
> But what if, for example, one uses some descriptor/metaclass magic to
> make it so that each subsequent access to the attribute returns a method
> bound to different objects?

Well, that's the whole problem with dynamism vs optimization...
From: Terry Reedy on
On 3/17/2010 1:35 AM, Patrick Maupin wrote:
>>>> def a(s, count, lenfunc):
> ... for i in xrange(count):
> ... z = lenfunc(s)
> ...
>>>> >>> a('abcdef', 100000000, len)
>>>> >>> a('abcdef', 100000000, str.__len__)
> Running cPython 2.6 on my machine, len() runs about 3 times faster
> than str.__len__(). The overhead of checking that an object is usable
> with a particular class method far outweighs the cost of creating the
> bound method!

Wow, this so surprised me, that I had to try it with 3.1 (on winxp), and
got a similar result (about 2.6x longer with str.__len__). This is a
real lesson in measure, don't guess, and how premature 'optimization'
may be a pessimization. Thanks.

Terry Jan Reedy