Decorator to inject function into __call__ of a class
Steven D'Aprano
steve at REMOVE-THIS-cybersource.com.au
Sat Mar 13 14:48:28 EST 2010
On Sat, 13 Mar 2010 11:02:44 -0800, Jon Clements wrote:
> If I can re-explain slightly, say I have a class 'compute':
>
> class Compute(object):
> def __init__(self, something):
> self.something = something
> # misc other methods here.....
>
> then...
>
> class ComputeAdd(Compute):
> pass
What's the purpose of the do-nothing subclass?
> If I do,
>
> @inject
> def ComputeAdd(fst, snd):
> return fst + snd
>
> The end result should be a new class called ComputeAdd __init__'d with
> fst and snd,
That will cause a TypeError, because ComputeAdd inherits __init__ from
Compute, which only takes a single argument. So you can't initialise it
with two.
> which when called, returns fst + snd.
>
> Hope that makes sense.
None what so ever, even after reading the entire thread :-)
Forget about the *mechanism*, and focus on the *result* you want. Let me
see if I can guess what result you want.
You want to start with a single base class, say Compute as defined above.
Then you want to write a function which interacts with Compute somehow,
say:
def func(self, x, y):
return self.something + x + y
and wave some sort of magic wand (a decorator? something else?) to get an
object x so that:
x("a", "b")
returns self.something + "a" + "b".
Is that right? If not, I have no idea what you want! But if this is what
you want, then this is probably the simplest approach:
Start by adding delegation to the Compute class:
class Compute(object):
def __init__(self, something):
self.something = something
def __call__(self, *args, **kwargs):
return self.function(*args, **kwargs)
Then you can initialise an instance of Compute, and add a function to it:
def func(self, x, y):
return self.something + x + y
added = Computer("spam")
added.function = func
And then say:
added("ham", "eggs")
-> "spamhameggs"
You could possibly even turn this into a decorator:
# untested
def magic(baseclass, *args):
instance = baseclass(*args)
def decorator(func):
instance.function = func
return instance
return decorator
@magic(Compute, "spam")
def func(self, x, y):
return self.something + x + y
func("ham", "eggs")
-> "spamhameggs"
Hope this helps.
--
Steven
More information about the Python-list
mailing list