2

I have a function, say:

def func(arg1, arg2=5): blah blah 

Unfortunately, a library that I'm using asks for an input to be instance of a class, so I cannot just pass my custom made function above.

I need a class wrapper around it, so that I pass: MyClass(arg2=4) and the result is the function shown above, ready to be executed with its second argument set to 4.

How can I do that?

My attempt: lambda x: func(x, arg2=4)

However, this is not an instance of a class. I want to mimic that library where their functions are instances of classes.

1

2 Answers 2

5

you can use the __call__ function of a class.

class CallableObject(object): def __init__(self, f): self.f = f def __call__(self, *args, **kwargs): return self.f(*args, **kwargs) 

then you can "call" the class like this:

def func(arg1, arg2=5): return arg1 + arg2 callable_object = CallableObject(func) callable_object(1, 3) 

returns 4

args in __init__

To give arguments when instantiating the class you can add them to init.

class CallableObject(object): def __init__(self, f, *args, **kwargs): self.f = f self.args = args self.kwargs = kwargs def __call__(self): return self.f(*self.args, **self.kwargs) 

Usage then becomes:

def func(arg1, arg2=5): return arg1 + arg2 callable_object = CallableObject(func, 1, arg2=3) callable_object() 

returning 4

and you can still call

def func(arg1, arg2=5): return arg1 + arg2 callable_object = CallableObject(func, 1) callable_object() 

returning 6 (arg2 = 5)

Sign up to request clarification or add additional context in comments.

3 Comments

I think this is what I'm looking for. Except that it is not exactly what I imagined. I thought I wouldn't need to redefine the function inside the class.
What about one of the arguments being set while instantiating the class? which is arg2 in my example
just move the *args, **kwargs, see updated answer
2

Using metaclass, you can solve this

class MetaClass(type): @staticmethod def wrap(run): """Return a wrapped instance method""" def outer(self): print "PRE", return_value = run(self) print "POST" return return_value return outer def __new__(cls, name, bases, attrs): """If the class has a 'run' method, wrap it""" if 'run' in attrs: attrs['run'] = cls.wrap(attrs['run']) return super(MetaClass, cls).__new__(cls, name, bases, attrs) class MyClass(object): """Use MetaClass to make this class""" __metaclass__ = MetaClass def run(self): print 'RUN', myinstance = MyClass() myinstance.run() 

1 Comment

I think this is too complicated for me. But I will start looking into this metaclass beast. Thanks.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.