From: Andre Engels on
On Thu, Mar 11, 2010 at 2:30 PM, Steve Holden <steve(a)holdenweb.com> wrote:

>> The example I showed was just a toy problem.  The real problem is
>> I expect to call a function many times, and I want to avoid the overhead of
>> the 'if blah' everytime.
>>
> This is a premature optimization. First, make it work. Then (if it
> doesn't work fast enough) make it work faster.

Corrolary: When you do make it faster, make it faster where it is slow.
Second corrolary: If making it fast is so important that these two
rules do not apply, Python is not your language of choice.


--
André Engels, andreengels(a)gmail.com
From: MRAB on
Andre Engels wrote:
> On Thu, Mar 11, 2010 at 2:30 PM, Steve Holden <steve(a)holdenweb.com> wrote:
>
>>> The example I showed was just a toy problem. The real problem is
>>> I expect to call a function many times, and I want to avoid the overhead of
>>> the 'if blah' everytime.
>>>
>> This is a premature optimization. First, make it work. Then (if it
>> doesn't work fast enough) make it work faster.
>
> Corrolary: When you do make it faster, make it faster where it is slow.
> Second corrolary: If making it fast is so important that these two
> rules do not apply, Python is not your language of choice.
>
Addendum: a bad algorithm is bad, whatever language it's written in.
From: Steve Howell on
On Mar 10, 7:18 pm, Steven D'Aprano
<ste...(a)REMOVE.THIS.cybersource.com.au> wrote:
> On Wed, 10 Mar 2010 08:12:14 -0500, Neal Becker wrote:
> > Want to switch __call__ behavior.  Why doesn't this work?  What is the
> > correct way to write this?
>
> > class X (object):
> >     def __init__(self, i):
> >         if i == 0:
> >             def __call__ (self):
> >                 return 0
> >         else:
> >             def __call_ (self):
> >                 return 1
>
> Others have already pointed out that there are two reasons that won't
> work:
>
> (1) you define __call__ as a local variable of the __init__ method which
> then disappears as soon as the __init__ method completes; and
>
> (2) special methods like __call__ are only called on the class, not the
> instance, so you can't give each instance its own method.
>

Are you sure about that? This program prints 1, 2, 1, 2.

class Foo:
def __init__(self, a):
if a == 1:
self.__call__ = lambda: 1
else:
self.__call__ = lambda: 2

foo1 = Foo(1)
print foo1()

foo2 = Foo(2)
print foo2()

print foo1()
print foo2()

See here:

http://docs.python.org/reference/datamodel.html

Class instances
Class instances are described below. Class instances are callable
only when the class has a __call__() method; x(arguments) is a
shorthand for x.__call__(arguments).
From: Peter Otten on
Steve Howell wrote:

> On Mar 10, 7:18 pm, Steven D'Aprano
> <ste...(a)REMOVE.THIS.cybersource.com.au> wrote:

>> (2) special methods like __call__ are only called on the class, not the
>> instance, so you can't give each instance its own method.

> Are you sure about that? This program prints 1, 2, 1, 2.

You are using a classic class while the behaviour described above applies to
newstyle classes:

>>> class Foo:
.... def __init__(self):
.... self.__call__ = lambda: 42
....
>>> Foo()()
42
>>> class Bar(object):
.... def __init__(self):
.... self.__call__ = lambda: 42
....
>>> Bar()()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'Bar' object is not callable

I don't think it's a good idea to write new code that requires a classic
class.

Peter
From: Steven D'Aprano on
On Thu, 11 Mar 2010 08:20:14 -0800, Steve Howell wrote:

>> (2) special methods like __call__ are only called on the class, not the
>> instance, so you can't give each instance its own method.
>>
>>
> Are you sure about that? This program prints 1, 2, 1, 2.

The rules for classic classes are different. Since classic classes have
gone away in 3.0, and are becoming rarer in 2.x, I didn't bother to
mention the complication.



--
Steven