From: Ethan Furman on
Patrick Maupin wrote:
> On Apr 2, 1:21 pm, Ethan Furman <et...(a)stoneleaf.us> wrote:
>> For this type of situation, my preference would be:
>>
>> class spam(object):
>> def __call__(self, x, y, z):
>> try:
>> mongo = self.mongo
>> except AttributeError:
>> mongo = self.mongo = heavy_lifting_at_runtime()
>> return frobnicate(x, y, z, mongo)
>> spam = spam()
>>
>> No extra objects, out-of-place underscores, etc.
>>
>> ~Ethan~
>
> Well, I'm not a big fan of unnecessary try/except, so I would at least
> change it to:
>
> class spam(object):
> def __getattr__(self, name):
> if name != 'mongo':
> raise AttributeError
> self.mongo = heavy_lifting_at_runtime()
> return self.mongo
> def __call__(self, x, y, z):
> return frobnicate(x, y, z, self.mongo)
> spam = spam()
>
> Regards,
> Pat


Sounds like a personal preference issue, rather than a necessary /
unnecessary issue -- after all, if you call that function a thousand
times, only once is mongo not defined... clearly the exception. ;)

~Ethan~
From: Patrick Maupin on
On Apr 2, 2:38 pm, Ethan Furman <et...(a)stoneleaf.us> wrote:
> Patrick Maupin wrote:
> > On Apr 2, 1:21 pm, Ethan Furman <et...(a)stoneleaf.us> wrote:
> >> For this type of situation, my preference would be:
>
> >> class spam(object):
> >>      def __call__(self, x, y, z):
> >>          try:
> >>              mongo = self.mongo
> >>          except AttributeError:
> >>              mongo = self.mongo = heavy_lifting_at_runtime()
> >>          return frobnicate(x, y, z, mongo)
> >> spam = spam()
>
> >> No extra objects, out-of-place underscores, etc.
>
> >> ~Ethan~
>
> > Well, I'm not a big fan of unnecessary try/except, so I would at least
> > change it to:
>
> > class spam(object):
> >      def __getattr__(self, name):
> >          if name != 'mongo':
> >              raise AttributeError
> >          self.mongo = heavy_lifting_at_runtime()
> >          return self.mongo
> >      def __call__(self, x, y, z):
> >          return frobnicate(x, y, z, self.mongo)
> > spam = spam()
>
> > Regards,
> > Pat
>
> Sounds like a personal preference issue, rather than a necessary /
> unnecessary issue -- after all, if you call that function a thousand
> times, only once is mongo not defined... clearly the exception.  ;)
>
> ~Ethan~

Well, I think the whole discussion has basically been about personal
preference. OTOH, but if you call the function a few million times,
you might find the cost of try/except to be something that you would
rather not incur -- it might become a performance issue rather than a
personal choice issue. On the other OTHER hand, if you call the
function a few billion times, performance weighs more heavily in favor
of the closure approach rather than the object approach, since local
variable lookup is so much cheaper.

Regards,
Pat
From: Ethan Furman on
Patrick Maupin wrote:

[snippage]

> Well, I think the whole discussion has basically been about personal
> preference. OTOH, but if you call the function a few million times,
> you might find the cost of try/except to be something that you would
> rather not incur -- it might become a performance issue rather than a
> personal choice issue. On the other OTHER hand, if you call the
> function a few billion times, performance weighs more heavily in favor
> of the closure approach rather than the object approach, since local
> variable lookup is so much cheaper.

Indeed. I was surprised to find your __getattr__ approach faster than
the try/except approach (about 20% on my machine). I'll have to think
about that for future situations like this.

My main point, though, was using __call__, and not some weird _ method. ;)

~Ethan~
From: Patrick Maupin on
On Apr 2, 3:33 pm, Ethan Furman <et...(a)stoneleaf.us> wrote:
> My main point, though, was using __call__, and not some weird _ method.  ;)

Yes, __call__ is good. In general, not naming things that don't need
to be named is good (but if you have too many of them to keep track
of, then, obviously, they need to be named, hence named tuples).

But I didn't need to address that, since you already did :-)
From: kj on
In <Xns9D4EC021DC8EAduncanbooth(a)127.0.0.1> Duncan Booth <duncan.booth(a)invalid.invalid> writes:

>class Spam(object):
> mongo = None
> def __call__(self, x, y, z):
> if self.mongo is None:
> self.mongo = heavy_lifting_at_runtime()
> return frobnicate(x, y, z, self.mongo)
>spam = Spam()

>ham = spam(1, 2, 3)

I really like this. Thanks.

>That's natural and readable.

From reading this thread, and the "(a==b) ? 'Yes' : 'No'" one, the
inescapable conclusion is that "readability" (like beauty) is very
much in the eye of the beholder, or, in this case, in the eye of
Guido.

~K