Redefining __call__ in an instance
Jason Mobarak
jmob at nospam__unm.edu
Thu Jan 15 19:55:52 EST 2004
def firstFunc (s, word='up'):
print "foo"
class callNoWork(object):
def __new__ (cls):
cls.__call__ = firstFunc
return object.__new__(cls)
callNoWork()()
# Dunno if you've read this, but it explains this:
# http://python.org/2.2.1/descrintro.html
Robert Ferrell wrote:
> I have a question about assigning __call__ to an instance to make that
> instance callable. I know there has been quite a bit of discussion
> about this, and I've read all I can find, but I'm still confused.
>
> I'd like to have a factory class that takes a string argument and returns
> the appropriate factory method based on that string. I'd like the
> instances to be callable. Like this:
>
> fact = Factory('SomeThing')
> aSomeThing = fact(some args)
>
> anotherFact = Factory('SomeThingElse')
> anotherThing = anotherFact(some other args)
>
> The way I thought to do this was to assign the __call__ attribute of
> the fact instance to the appropriate factory method in __init__. That does not
> work, as many others have pointed out. I know there are workarounds.
> The appended code shows the variants I know of. I can use one of
> them, but they are not quite what I am looking for.
>
> Have I missed the key message that explains how to make new-style
> classes callable, with the called method unique to each instance?
>
> thanks,
> -robert
>
> """Test use of __call__ in a (new style) class.
> The classes below show various ways of making instances
> of a class callable. The goal is to make an instance callable,
> with the called method defined distincly for each instance.
> """
>
>
> def firstFunc(word = 'up'):
> """This is the method to call, when an instance is invoked."""
> print "This is firstFunc, word %s." % word
> return
>
> class callWorks(object):
> """This works, since the called method is defined in the class."""
> def __init__(self):
> pass
> def __call__(self, word = 'up'):
> print 'This is inside callWorks, word %s.' % word
> return
>
> class callNoWork(object):
> """This doesn't work, since __call__ is defined for the method,
> not the class."""
> def __init__(self):
> # This does not make an instance of callNoWork callable
> self.__call__ = firstFunc
>
> class callWorksNoFun(object):
> """This works, but since the class's method is being called, the
> default arguments are defined by the class, and do not
> properly reflect the default arguments of the method that
> wants to be called."""
> def __init__(self):
> self._callFunc = firstFunc
> def __call__(self, word = None):
> # Although an instance of callWorksNoFun is callable,
> # the default arguments are wrong
> self._callFunc(word)
> return
>
> class addCallAttribute(object):
> """Add the attribute 'callMe', which is the callable function.
> This works fine, but requires the user to invoke this as
> instance.callMe(), rather than just instance()."""
> def __init__(self):
> self.callMe = firstFunc
>
> # Simplest thing
> cw = callWorks()
> cw()
>
> # Natural thing to try, but doesn't work
> cnw = callNoWork()
> # The instance, cnw, is not callable.
> try:
> cnw()
> except Exception, exception:
> print 'Call did not work, gave exception: %s.' % exception
>
> # Works, but actually invoking class method, not instance's method
> cwNF = callWorksNoFun()
> # The instance cwNF is callable, but the default value for the callable is wrong.
> # This works fine
> cwNF('No up')
> # This should default to print 'Up', but instead it defaults to None.
> cwNF()
>
> # Fine, but requires user to invoke instance.callMe(), rather than just instance().
> aCA = addCallAttribute()
> # To call the instance, use the callMe attribute. That respects defaults fine.
> aCA.callMe()
--
(------------------------------(
)~~~~~ Jason A. Mobarak ~~~~~~~)
(~~ aether_at_gentoo_dot_org ~~(
)~~~~ jmob_at_unm_dot_edu ~~~~~)
(------------------------------(
More information about the Python-list
mailing list