Re: changing __call__ on demand

2005-02-14 Thread Michael Hoffman
Stefan Behnel wrote:
Thanks for the quick answer. I didn't know they were class-level 
methods. Too bad. Guess I'll stick with indirection then.
Here is one way of doing that indirection I just thought of--have
the class __call__ attribute call on the instance __call__
attribute:
 class MyClass(object):
... def __init__(self, func):
... self.__call__ = func
... def __call__(self, *args, **keywds):
... return self.__call__(*args, **keywds)
...
 def f1(): return foo
...
 def f2(x, y): return x+y
...
 MyClass(f1)()
'foo'
 MyClass(f2)(30, 12)
42
I still can't figure out whether this is elegant, or opaque and
to be avoided. wink
--
Michael Hoffman
--
http://mail.python.org/mailman/listinfo/python-list


Re: changing __call__ on demand

2005-02-14 Thread Hans Nowak
Stefan Behnel wrote:
Hi!
This somewhat puzzles me:
Python 2.4 (#1, Feb  3 2005, 16:47:05)
[GCC 3.3.4 (pre 3.3.5 20040809)] on linux2
Type help, copyright, credits or license for more information.
. class test(object):
...   def __init__(self):
... self.__call__ = self.__call1
...   def __call1(self):
... print 1
...   def __call__(self):
... print 2
...
. t = test()
. t()
2
If I take out the __call__ method completely and only set it in 
__init__, I get a TypeError saying that test is not callable.
Note that it works just fine if you don't use a new-style class:
 class Test:
... def __init__(self):
... self.__call__ = self.foobar
... def foobar(self, *args, **kwargs):
... print Called with:, args, kwargs
...
 t = Test()
 t()
Called with: () {}
 t(3, 4)
Called with: (3, 4) {}
 t(42, x=0)
Called with: (42,) {'x': 0}
--
Hans Nowak
http://zephyrfalcon.org/
--
http://mail.python.org/mailman/listinfo/python-list


changing __call__ on demand

2005-02-13 Thread Stefan Behnel
Hi!
This somewhat puzzles me:
Python 2.4 (#1, Feb  3 2005, 16:47:05)
[GCC 3.3.4 (pre 3.3.5 20040809)] on linux2
Type help, copyright, credits or license for more information.
. class test(object):
...   def __init__(self):
... self.__call__ = self.__call1
...   def __call1(self):
... print 1
...   def __call__(self):
... print 2
...
. t = test()
. t()
2
If I take out the __call__ method completely and only set it in __init__, I 
get a TypeError saying that test is not callable.

I want to use this in order to provide different implementations based on the 
object configuration. Calculating the right function to call is non-trivial 
and calls are frequent, so I want to change __call__ in order to run the right 
function directly.

I know, I could use another level of indirection:
def __call__(self):
  self.the_right_method()
and then set the_right_method accordingly, but I find that somewhat 
sub-optimal. Is there a way to change __call__ after class creation?

Stefan
--
http://mail.python.org/mailman/listinfo/python-list


Re: changing __call__ on demand

2005-02-13 Thread Alan McIntyre
I tried this:
class test(object):
... def __call1(self):
... print 1
... __call__ = __call1
...
t = test()
t()
1

Is that what you were looking for?
--
Alan McIntyre
ESRG LLC
http://www.esrgtech.com
Stefan Behnel wrote:
Hi!
This somewhat puzzles me:
Python 2.4 (#1, Feb  3 2005, 16:47:05)
[GCC 3.3.4 (pre 3.3.5 20040809)] on linux2
Type help, copyright, credits or license for more information.
. class test(object):
...   def __init__(self):
... self.__call__ = self.__call1
...   def __call1(self):
... print 1
...   def __call__(self):
... print 2
...
. t = test()
. t()
2
If I take out the __call__ method completely and only set it in 
__init__, I get a TypeError saying that test is not callable.

I want to use this in order to provide different implementations based 
on the object configuration. Calculating the right function to call is 
non-trivial and calls are frequent, so I want to change __call__ in 
order to run the right function directly.

I know, I could use another level of indirection:
def __call__(self):
  self.the_right_method()
and then set the_right_method accordingly, but I find that somewhat 
sub-optimal. Is there a way to change __call__ after class creation?

Stefan
--
http://mail.python.org/mailman/listinfo/python-list


Re: changing __call__ on demand

2005-02-13 Thread Michael Hoffman
Stefan Behnel wrote:
Is there a way to change __call__ after class creation?
__call__, like __getitem__, and __getattr__ is called on the
class object, not the instance object. So, no, not as far as I
am aware, without using metaclass trickery. The simplest option
IMO is to use another level of indirection as you suggest.
--
Michael Hoffman
--
http://mail.python.org/mailman/listinfo/python-list


Re: changing __call__ on demand

2005-02-13 Thread Michael Hoffman
Alan McIntyre wrote:
class test(object):
...def __call1(self):
...print 1
...__call__ = __call1
Is that what you were looking for?
That still only allows him to have one call function per class.
--
Michael Hoffman
--
http://mail.python.org/mailman/listinfo/python-list


Re: changing __call__ on demand

2005-02-13 Thread Stefan Behnel
Michael Hoffman schrieb:
__call__, like __getitem__, and __getattr__ is called on the
class object, not the instance object. So, no, not as far as I
am aware, without using metaclass trickery. The simplest option
IMO is to use another level of indirection as you suggest.
Thanks for the quick answer. I didn't know they were class-level methods. Too 
bad. Guess I'll stick with indirection then.

Stefan
--
http://mail.python.org/mailman/listinfo/python-list


Re: changing __call__ on demand

2005-02-13 Thread Steven Bethard
Stefan Behnel wrote:
Is there a way to change __call__ after class creation?
Check out this thread on the topic:
http://mail.python.org/pipermail/python-list/2004-January/203142.html
Basically, the answer is no -- at least not on a per-instance basis. 
You can try something like:

py class Test(object):
... def __new__(cls):
... cls.__call__ = cls.call1
... return object.__new__(cls)
... def call1(self):
... print 'call1'
... def __call__(self):
... print '__call__'
...
py Test()()
call1
But then the call method is changed for all instances:
py class Test(object):
... instances = 0
... def __new__(cls):
... if cls.instances == 1:
... print setting __call__
... cls.__call__ = cls.call1
... cls.instances += 1
... return object.__new__(cls)
... def call1(self):
... print 'call1'
... def __call__(self):
... print '__call__'
...
py t1 = Test()
py t1()
__call__
py t2 = Test()
setting __call__
py t2()
call1
py t1()
call1
Steve
--
http://mail.python.org/mailman/listinfo/python-list


Re: changing __call__ on demand

2005-02-13 Thread Kent Johnson
Stefan Behnel wrote:
Hi!
This somewhat puzzles me:
Python 2.4 (#1, Feb  3 2005, 16:47:05)
[GCC 3.3.4 (pre 3.3.5 20040809)] on linux2
Type help, copyright, credits or license for more information.
. class test(object):
...   def __init__(self):
... self.__call__ = self.__call1
...   def __call1(self):
... print 1
...   def __call__(self):
... print 2
...
. t = test()
. t()
2
It works the way you want if test is an old-style class:
  class test:
 ...  def __init__(self):
 ...self.__call__ = self.__call1
 ...  def __call1(self):
 ...print 1
 ...  def __call__(self):
 ...print 2
 ...
  t=test()
  t()
1
Kent
--
http://mail.python.org/mailman/listinfo/python-list


Re: changing __call__ on demand

2005-02-13 Thread Alan McIntyre
Thanks; I didn't read close enough. :)
--
Alan McIntyre
ESRG LLC
http://www.esrgtech.com
Michael Hoffman wrote:
Alan McIntyre wrote:
class test(object):
...def __call1(self):
...print 1
...__call__ = __call1
Is that what you were looking for?

That still only allows him to have one call function per class.
--
http://mail.python.org/mailman/listinfo/python-list