[Python-ideas] Add 'composable' decorator to functools (with @ matrix multiplication)

Erik Bray erik.m.bray at gmail.com
Wed May 6 16:10:22 CEST 2015


On Wed, May 6, 2015 at 9:20 AM, Ivan Levkivskyi <levkivskyi at gmail.com> wrote:
> Dear all,
>
> The matrix multiplication operator @ is going to be introduced in Python 3.5
> and I am thinking about the following idea:
>
> The semantics of matrix multiplication is the composition of the
> corresponding linear transformations.
> A linear transformation is a particular example of a more general concept -
> functions.
> The latter are frequently composed with ("wrap") each other. For example:
>
> plot(real(sqrt(data)))
>
> However, it is not very readable in case of many wrapping layers. Therefore,
> it could be useful to employ
> the matrix multiplication operator @ for indication of function composition.
> This could be done by such (simplified) decorator:
>
> class composable:
>
>     def __init__(self, func):
>         self.func = func
>
>     def __call__(self, arg):
>         return self.func(arg)
>
>     def __matmul__(self, other):
>         def composition(*args, **kwargs):
>             return self.func(other(*args, **kwargs))
>         return composable(composition)
>
> I think using such decorator with functions that are going to be deeply
> wrapped
> could improve readability.
> You could compare (note that only the outermost function should be
> decorated):
>
> plot(sorted(sqrt(real(data_array)))) vs. (plot @ sorted @ sqrt @ real)
> (data_array)
>
> I think the latter is more readable, also compare
>
> def sunique(lst):
>     return sorted(list(set(lst)))
>
> vs.
>
> sunique = sorted @ list @ set
>
> Apart from readability, there are following pros of the proposed decorator:
>
> 1. Similar semantics as for matrix multiplication.
> 2. Same symbol for composition as for decorators.
> 3. The symbol @ resembles mathematical notation for function composition: ∘
>
> I think it could be a good idea to add such a decorator to the stdlib
> functools module.

In the astropy.modeling package, which consists largely of collection
of fancy wrappers around analytic functions,
we used the pipe operator | (that is, __or__) to implement function
composition, as demonstrated here:

http://docs.astropy.org/en/stable/modeling/compound-models.html#model-composition

I do like the idea of using the new @ operator for this purpose--it
makes sense as a generalization of linear operators,
and it just looks a little more like the circle operator often used
for functional composition.  On the other hand
I'm also fond of the choice to use |, for the similarity to UNIX shell
pipe operations, as long as it can't be confused with
__or__.  Point being something like this could be implemented now with __or__.

I think this is simple enough that it doesn't need to be in the
stdlib, especially if there are different ways people
would like to do this.  But I do like the idea.

Erik


More information about the Python-ideas mailing list