0

I have a code like this. In my original code I would like to call two or more methods when a button is clicked.

class MyApp(object): @staticmethod def combine_funcs(*funcs): def combined_func(*args, **kwargs): for f in funcs: f(*args, **kwargs) return combined_func def __init__(self): MyApp.combine_funcs(self.my_first_func, self.my_second_func) def my_first_func(self): print("First") def my_second_func(self): print("Second") my_app = MyApp() 

When I run this nothing is printed. Why?

7
  • 5
    You're just combining the functions, you're not calling your newly combined functions function. Commented May 30, 2018 at 12:34
  • Ok, thanks. I need parenthesis. However when I want to call them when a button is pressed self.ui.pushButton.clicked.connect(MyApp.combine_funcs(self.converter(), self.showMessage())) is it the same? They are immediately called, not waiting for a mouse click? Commented May 30, 2018 at 12:45
  • combine_funcs(self.converter(), ...) is not the same as combine_funcs(self.my_first_func, ...), now is it? Commented May 30, 2018 at 12:51
  • Ok, it seems I have more issues with my code. () executing a function. This is why my init didn't do anything. I understand that now. The second problem is when I remove () in self.ui.pushButton.clicked.connect(MyApp.combine_funcs(self.converter, self.showMessage)) I get an error converter() takes 1 positional argument but 2 were given. Converter function takes only self argument. What 2 arguments am I sending? Commented May 30, 2018 at 12:59
  • When it is finally called, it is being passed arguments… Commented May 30, 2018 at 13:03

2 Answers 2

2

A method is not much more than a member of a class that happens to be a function. The magic is just that when it is called on an object (a.func(x...)) the object is automatically prepended in the argument list resulting in the actual call A.func(a, x...).

What you want can be obtained that way:

class MyApp(object): # prepend with _ to "hide" the symbol def _combine_funcs(*funcs): def combined_func(*args, **kwargs): for f in funcs: f(*args, **kwargs) return combined_func def my_first_func(self): print("First") def my_second_func(self): print("Second") # actually declares combined as a method of MyClass combined = _combine_funcs(my_first_func, my_second_func) 

Usage:

>>> a = MyApp() >>> a.combined() First Second 

But a much cleaner way would be to use a decorator for that in Python 3:

import inspect def combine_funcs(*funcs): def outer(f): def combined_func(*args, **kwargs): # combine a bunch of functions for f in funcs: x = f(*args, *kwargs) return x # returns return value of last one combined_func.__doc__ = f.__doc__ # copy docstring and signature combined_func.__signature__ = inspect.signature(f) return combined_func return outer class MyApp(object): def my_first_func(self): print("First") def my_second_func(self): print("Second") @combine_funcs(my_first_func, my_second_func) def combined(self): """Combined function""" pass 

The decorator will replace the body but will keep the docstring and the signature of the original function (in Python 3). You can then use it normally:

>>> a = MyApp() >>> a.combined() First Second >>> help(a.combined) Help on method combined_func in module __main__: combined_func() method of __main__.MyApp instance Combined function >>> help(MyApp.combined) Help on function combined_func in module __main__: combined_func(self) Combined function 
Sign up to request clarification or add additional context in comments.

Comments

0

You're calling combine_funcs, but the function within that, combined_func, is not being called.

Is there a reason not to simplify to:

class MyApp(object): @staticmethod def combined_func(*args, **kwargs): for f in args: f() def __init__(self): MyApp.combined_func(self.my_first_func, self.my_second_func) def my_first_func(self): print("First") def my_second_func(self): print("Second") my_app = MyApp() 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.