From: Stephen Hansen on
On 2010-04-02 20:24:46 -0700, Patrick Maupin said:

> On Apr 2, 10:11�pm, Stephen Hansen <apt.shan...(a)gmail.invalid> wrote:
>>
>> I don't know if properties are really faster or slower then a
>> __getattr__, but I find them a lot cleaner if I want to delay some
>> calculation until needed like that.
>
> Well, the relative speed of properties vs. __getattr__ can become
> irrelevant in at least two ways:
>
> 1) If the __getattr__ only calculates the value one time and then
> stuffs it into the instance dictionary, now you are really comparing
> the relative speed of properties vs. lookup of an attribute in the
> instance dict. If you're at all concerned about speed, I think there
> is a clear winner here.

I concede it would probably be notably faster, but there's a big
difference between "at all concerned about speed" and "optimizing a
profiled bottleneck".

The speed difference between direct attribute lookup and properties may
be notable, but that doesn't make a clear winner here. Now that I have
(with either method) optimized the expensive value-calculation
operation such that it only happens on-demand and once, I now have to
weigh further optimization.

Is the difference in speed between a standard attribute lookup and a
property fetch worth losing the clarity the property brings over the
__getattr__ solution, especially considering the __getattr__ creates a
fuzzy 'sometimes this code is responsible, othertimes the dict is'
situation that someone may down the road miss in maintenance?

For me, usually not-- unless profiling pushes me to reconsider. But
everyone makes these calls differently.

> 2) There is a single __getattr__ function, vs. one property for every
> attribute that needs a property. In cases where you can somehow
> easily compute the attribute names as well as the attribute values,
> __getattr__ can be a *lot* less code than defining dozens of
> properties.

I don't really mind a lot of properties, if they're simple. Then again,
I often prefer regular ol' attributes where possible :) However, if I'm
doing a dispatching sort of mechanism, or a situation where the "name"
isn't something static, set in stone or pre-defined-- then certainly,
__getattr__ is a fine solution. I don't mind it where its the clearest
way to accomplish a goal.

--
--S

.... p.s: change the ".invalid" to ".com" in email address to reply privately.

From: John Nagle on
kj wrote:
> When coding C I have often found static local variables useful for
> doing once-only run-time initializations.

If you want functions with state, use an object. That's what they're
for. Don't muck with the internal representation of functions.

John Nagle
From: Patrick Maupin on
On Apr 4, 1:57 pm, John Nagle <na...(a)animats.com> wrote:
>     If you want functions with state, use an object. That's what they're
> for.  Don't muck with the internal representation of functions.
>

While "Don't muck with the internal representation of functions" is
excellent advice over 99% of the time, it is also true that it is
often possible, sometimes even encouraged, to have "functions with
state."

This is done without "mucking" and without explicitly declaring a
class or a class instance. See, e.g. closures and generator
functions.

Regards,
Pat
From: Lee Harr on

> Another approach would be to stuff the static values in the function's
> __dict__.

That's how I did it when I wanted something similar.

I created this decorator:


def static(**kw):
��� '''
��� Used to create a decorator function that will add an
��� attribute to a function and initialize it.

���>>> @static(foo=5)
��� ... def bar():
��� ...���� print bar.foo
��� ...���� bar.foo += 1
��� ...
���>>> bar()
��� 5
���>>> bar()
��� 6
��� '''

��� def decorator(f):
������� f.__dict__.update(kw)
������� return f
��� return decorator


_________________________________________________________________
Hotmail: Trusted email with Microsoft�s powerful SPAM protection.
https://signup.live.com/signup.aspx?id=60969
From: Ethan Furman on
Ethan Furman wrote:
> Steven D'Aprano wrote:
>> On Fri, 02 Apr 2010 19:48:59 -0700, Ethan Furman wrote:
>>
>>
>>>> The heuristic I use is, if I expect the try block to raise an exception
>>>> more than about one time in ten, I change to an explicit test. In this
>>>> case, since the exception should only be raised once, and then never
>>>> again, I would use a try...except block.
>>>
>>> That was my reasoning as well, but when I timed it for one million runs
>>> (so 1 instantiation, 999,999 simple calls), the __getattr__ time was .5
>>> seconds, the try...execpt block was .6; at ten million it was 5 and 6.
>>
>>
>> Care to share your timing code? Not that I don't trust your results,
>> but timings are very sensitive to the exact thing you do, and I'd like
>> to see what that is.
>
> Happy to do so -- if I made a mistake I'd like to know about it and learn.
>
> It'll have to wait two days 'til I get back to work, though... I'll post
> it asap.

Well, so much for asap, but here's what I used (with one correction: in
the 'if' code I had forgotten to actually reference the missing
attribute, so the __getattr__ look up never happened; now the
try...except block is /slightly/ faster, as opposed to 20% slower).


class spam_except(object):
def __call__(self, x, y, z):
try:
mongo = self.mongo
except AttributeError:
mongo = self.mongo = 1
return

class spam_if(object):
def __getattr__(self, name):
if name != 'mongo':
raise AttributeError
self.mongo = 1
return self.mongo
def __call__(self, x, y, z):
self.mongo # didn't have this line before. d'oh!
return


--> timeit.Timer('spammer(1,2,3)','from spam import spam_except;
spammer=spam_except()').timeit()
0.65764130543749388

--> timeit.Timer('spammer(1,2,3)','from spam import spam_if;
spammer=spam_if()').timeit()
0.66972877235545525

~Ethan~