operator.call / operator.__call__

A simple suggestion: add "operator.call" and "operator.__call__", which would provide a function like Python2's "apply" (but it'd be called with already unpacked arguments, i.e. operator.call(f, *args, **kwargs)). Why? To be able to pass it as an argument to other function, just like the other functions defined in the "operator" module. Antony

How would this be different from using functools.partial? On Wed, Oct 29, 2014, 23:40 Antony Lee <antony.lee@berkeley.edu> wrote:
A simple suggestion: add "operator.call" and "operator.__call__", which would provide a function like Python2's "apply" (but it'd be called with already unpacked arguments, i.e. operator.call(f, *args, **kwargs)). Why? To be able to pass it as an argument to other function, just like the other functions defined in the "operator" module.
Antony _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/

On Wed, Oct 29, 2014 at 03:39:59PM -0700, Antony Lee wrote:
A simple suggestion: add "operator.call" and "operator.__call__", which would provide a function like Python2's "apply" (but it'd be called with already unpacked arguments, i.e. operator.call(f, *args, **kwargs)). Why? To be able to pass it as an argument to other function, just like the other functions defined in the "operator" module.
I think you want something like this? def call(callable, *args, **kwargs): return callable(*args, **kwargs) Can you give an example of how you might use this call method? It doesn't have to be a real world use-case, just an illustration. Perhaps I'm being a bit dim-witted today, but I'm having trouble thinking of where I would use this operator.call rather than just directly applying *args, **kwargs to the callable. -- Steven

I have two use cases below. Yes, it is true that just defining the "call" function myself would only take me two lines, but on the other hand the same is true for most functions in the operator module... - Sometimes, depending on a switch, you want either to call a function directly, or to pass it to a specialized "caller", e.g. def run_in_thread(func, *args, **kwargs): Thread(target=func, args=args, kwargs=kwargs).start() def run_here_or_in_thread(in_thread, func, *args, **kwargs): (run_in_thread if in_thread else operator.call)(func, *args, **kwargs) or to optionally use a ContextDecorator: def run_in_ctx(ctx, func, *args, **kwargs): (ctx or operator.call)(func) - In Qt programs (although I assume similar ideas apply to other GUI toolkits), where functions that operate on the GUI can only be called from the main thread, but "signals" (in the Qt sense of the term) can be used to communicate between threads, I find it useful to define a "call this in the GUI thread" generic signal. The implementation is essentially class Main(QMainWindow): any_callable_signal = pyqtSignal(object) def __init__(self, *args, **kwargs): <...> self.any_callable_signal.connect(lambda f: f()) # <- operator.call seems to express this better. def call_in_gui_thread(self, func): self.any_callable_signal.emit(func) Antony 2014-10-29 17:57 GMT-07:00 Steven D'Aprano <steve@pearwood.info>:
A simple suggestion: add "operator.call" and "operator.__call__", which would provide a function like Python2's "apply" (but it'd be called with already unpacked arguments, i.e. operator.call(f, *args, **kwargs)). Why? To be able to pass it as an argument to other function, just like
On Wed, Oct 29, 2014 at 03:39:59PM -0700, Antony Lee wrote: the
other functions defined in the "operator" module.
I think you want something like this?
def call(callable, *args, **kwargs): return callable(*args, **kwargs)
Can you give an example of how you might use this call method? It doesn't have to be a real world use-case, just an illustration.
Perhaps I'm being a bit dim-witted today, but I'm having trouble thinking of where I would use this operator.call rather than just directly applying *args, **kwargs to the callable.
-- Steven _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/

(only referring to the second use case here) On 30.10.2014 09:07, Antony Lee wrote:
[snip] - In Qt programs (although I assume similar ideas apply to other GUI toolkits), where functions that operate on the GUI can only be called from the main thread, but "signals" (in the Qt sense of the term) can be used to communicate between threads, I find it useful to define a "call this in the GUI thread" generic signal. The implementation is essentially
class Main(QMainWindow): any_callable_signal = pyqtSignal(object) def __init__(self, *args, **kwargs): <...> self.any_callable_signal.connect(lambda f: f()) # <- operator.call seems to express this better. def call_in_gui_thread(self, func): self.any_callable_signal.emit(func)
How is that different from directly passing f? Or use functools.partial in case you need to pass additional, fixed arguments to f. regards, jwi
Antony
2014-10-29 17:57 GMT-07:00 Steven D'Aprano <steve@pearwood.info>:
A simple suggestion: add "operator.call" and "operator.__call__", which would provide a function like Python2's "apply" (but it'd be called with already unpacked arguments, i.e. operator.call(f, *args, **kwargs)). Why? To be able to pass it as an argument to other function, just like
On Wed, Oct 29, 2014 at 03:39:59PM -0700, Antony Lee wrote: the
other functions defined in the "operator" module.
I think you want something like this?
def call(callable, *args, **kwargs): return callable(*args, **kwargs)
Can you give an example of how you might use this call method? It doesn't have to be a real world use-case, just an illustration.
Perhaps I'm being a bit dim-witted today, but I'm having trouble thinking of where I would use this operator.call rather than just directly applying *args, **kwargs to the callable.
-- Steven _______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________ Python-ideas mailing list Python-ideas@python.org https://mail.python.org/mailman/listinfo/python-ideas Code of Conduct: http://python.org/psf/codeofconduct/

On Oct 30, 2014, at 1:23, Jonas Wielicki <j.wielicki@sotecware.net> wrote:
(only referring to the second use case here)
On 30.10.2014 09:07, Antony Lee wrote:
[snip] self.any_callable_signal.connect(lambda f: f()) # <- operator.call seems to express this better. def call_in_gui_thread(self, func): self.any_callable_signal.emit(func)
How is that different from directly passing f? Or use functools.partial in case you need to pass additional, fixed arguments to f.
He's passing a function that takes any function f and calls it. That's not the same as passing any particular function. Maybe it's more obvious if you compare: lambda f: f() lambda: f()

On 30.10.2014 10:03, Andrew Barnert wrote:
On Oct 30, 2014, at 1:23, Jonas Wielicki <j.wielicki@sotecware.net> wrote:
(only referring to the second use case here)
On 30.10.2014 09:07, Antony Lee wrote:
[snip] self.any_callable_signal.connect(lambda f: f()) # <- operator.call seems to express this better. def call_in_gui_thread(self, func): self.any_callable_signal.emit(func)
How is that different from directly passing f? Or use functools.partial in case you need to pass additional, fixed arguments to f.
He's passing a function that takes any function f and calls it. That's not the same as passing any particular function.
Maybe it's more obvious if you compare:
lambda f: f() lambda: f()
Right, I missed that, sorry for the noise. regards, jwi

On 10/30/2014 4:07 AM, Antony Lee wrote:
I have two use cases below. Yes, it is true that just defining the "call" function myself would only take me two lines, but on the other hand the same is true for most functions in the operator module...
The primary intended use of operator.op functions is to be passed as arguments since operators themselves cannot be. By exposing C-coded wrappers, they make this possible more efficiently than would be the case with Python wrappers. There never seemed to be a need to pass 'apply' itself as an argument, and the newer of f(*args, **kwds) made its direct use unneeded. Hence it was deleted. The signature of apply is apply(func, arg[, keywords]). The arguments are not unpacked just to be repacked and unpacked again, as would happen with your renamed version of apply.
- Sometimes, depending on a switch, you want either to call a function directly, or to pass it to a specialized "caller", e.g.
Then either call it directly or pass it to a specialized caller.
def run_in_thread(func, *args, **kwargs): Thread(target=func, args=args, kwargs=kwargs).start()
In its use below, this would be more efficient as def run_in_thread(func, args, kwargs):
def run_here_or_in_thread(in_thread, func, *args, **kwargs): (run_in_thread if in_thread else operator.call)(func, *args, **kwargs)
With the altered sig, this can be written (run_in_thread(func, args, kwargs) if in_thread else func(*args, **kwargs)) -- Terry Jan Reedy
participants (6)
-
Andrew Barnert
-
Antony Lee
-
Jonas Wielicki
-
Steven D'Aprano
-
Terry Reedy
-
Yann Kaiser