[Python-ideas] @partials = decorators

Ron Adam ron3200 at gmail.com
Sat Feb 8 23:41:54 CET 2014



On 02/08/2014 11:55 AM, Ron Adam wrote:
>
> On 02/06/2014 05:14 AM, Nick Coghlan wrote:> On 6 February 2014 20:34, Ron
> Adam<ron3200 at gmail.com>  wrote:

> Hmmm...  Could the @ syntax be generalised in this case?
>
>       @foo(func)    Partial waiting for rest...
>
>
> Then the more general case...
>
>       a_op = @foo(op)   # Partial waiting for rest.
>       a_x = @a_op(x)
>       a = a_x(y)
>
> That would be cool, unifies decorators and partials with decorator syntax!
>
>
> I think it's even back-words compatible if you allow this equivalency.
>
>      def foo(x, y):
>         ...
>
>      @foo(x, y)  ==  foo(x, y)    # An identity partial
>
>
> And the decorator case becomes...
>
>      @partial
>      def func():
>        ...
>
> And we get this equivalency as well....
>
>      @partial == partial       # I think this could work.
>
>
> The reason these things are interesting to me is that, I've been thinking
> about the order of function arguments and if there could be some
> generalised concepts that can be applied to that problem.  Being able to
> use normal functions effectively in these ways,  (with partials, and
> continuations), is related to the order of the arguments and how they are
> commonly used.

Here's a rough python version...  It currently gets tripped up on optional 
arguments, but it does work for non optional cases.

I think a builtin, along with the new signatures capabilities could fix 
those cases.

(and to address Stevens conserns.. It would be explicit and won't effect 
the beginner cases if you don't use the @...

In this example I'm using P.  And a builtin function could work just as 
well.  Although I would like the @ syntax to just work without the function.

It's just a first attempt, with probably a lot of issues to be handled 
still, but it does show it's doable.

Cheers,
    Ron


#-------------------------------

# A builtin could do this much better.
class P:
     def __init__(self, f, *args, **kwds):
         self.f = f
         self.args = args
         self.kwds = kwds
     def __call__(self, *args, **kwds):
         args = list(self.args) + list(args)
         kwds.update(self.kwds)
         try:
             return self.f(*args, **kwds)
         except TypeError:
             return self.__class__(self.f, *args, **kwds)


#  This the easy way to write decorators!!!  :-)
@P
def deco(f, *args):
     print("Got: ", args)
     return f(*args)


# And a partial function example with it.  :-)
@P
@deco
def foo(x, y, z):
     return x + y + z

print(foo(1, 2, 3))
print(foo(1, 2)(3))
print(foo(1)(2)(3))
#-------------------------

The output...

ra:~ >python3 partial_deco.py
Got:  ()
Got:  (1, 2, 3)
6
Got:  (1, 2)
Got:  (1, 2, 3)
6
Got:  (1,)
Got:  (1, 2)
Got:  (1, 2, 3)
6







More information about the Python-ideas mailing list