update from Peter Harris; minor edits
This commit is contained in:
parent
4957e14b72
commit
867839cff4
57
pep-0309.txt
57
pep-0309.txt
|
@ -18,8 +18,11 @@ This proposal is for a function or callable class that allows a new
|
||||||
callable to be constructed from a callable and a partial argument list
|
callable to be constructed from a callable and a partial argument list
|
||||||
(including positional and keyword arguments).
|
(including positional and keyword arguments).
|
||||||
|
|
||||||
I propose a standard library module called "functional", to hold useful
|
I propose a standard library module called "functional", to hold
|
||||||
higher-order functions, including the implementation of partial().
|
useful higher-order functions, including the implementation of
|
||||||
|
partial().
|
||||||
|
|
||||||
|
An implementation has been submitted to SourceForge [2]_.
|
||||||
|
|
||||||
|
|
||||||
Motivation
|
Motivation
|
||||||
|
@ -52,8 +55,9 @@ always knows the number of arguments expected and can do the right
|
||||||
thing when presented with a functor and less arguments than expected.
|
thing when presented with a functor and less arguments than expected.
|
||||||
|
|
||||||
Python does not implement multi-argument functions by currying, so if
|
Python does not implement multi-argument functions by currying, so if
|
||||||
you want a function with partially-applied arguments you would probably
|
you want a function with partially-applied arguments you would
|
||||||
use a lambda as above, or define a named function for each instance.
|
probably use a lambda as above, or define a named function for each
|
||||||
|
instance.
|
||||||
|
|
||||||
However, lambda syntax is not to everyone's taste, so say the least.
|
However, lambda syntax is not to everyone's taste, so say the least.
|
||||||
Furthermore, Python's flexible parameter passing using both positional
|
Furthermore, Python's flexible parameter passing using both positional
|
||||||
|
@ -61,8 +65,8 @@ and keyword presents an opportunity to generalise the idea of partial
|
||||||
application and do things that lambda cannot.
|
application and do things that lambda cannot.
|
||||||
|
|
||||||
|
|
||||||
Rationale
|
Example Implementation
|
||||||
=========
|
======================
|
||||||
|
|
||||||
Here is one way to do a create a callable with partially-applied
|
Here is one way to do a create a callable with partially-applied
|
||||||
arguments in Python. The implementation below is based on improvements
|
arguments in Python. The implementation below is based on improvements
|
||||||
|
@ -90,6 +94,9 @@ positional arguments are appended to those provided to the
|
||||||
constructor, and keyword arguments override and augment those provided
|
constructor, and keyword arguments override and augment those provided
|
||||||
to the constructor.
|
to the constructor.
|
||||||
|
|
||||||
|
Positional arguments, keyword arguments or both can be supplied at
|
||||||
|
when creating the object and when calling it.
|
||||||
|
|
||||||
|
|
||||||
Examples of Use
|
Examples of Use
|
||||||
===============
|
===============
|
||||||
|
@ -97,8 +104,8 @@ Examples of Use
|
||||||
So ``partial(operator.add, 1)`` is a bit like ``(lambda x: 1 + x)``.
|
So ``partial(operator.add, 1)`` is a bit like ``(lambda x: 1 + x)``.
|
||||||
Not an example where you see the benefits, of course.
|
Not an example where you see the benefits, of course.
|
||||||
|
|
||||||
Note too, that you could wrap a class in the same way, since
|
Note too, that you could wrap a class in the same way, since classes
|
||||||
classes themselves are callable factories for objects. So in some cases,
|
themselves are callable factories for objects. So in some cases,
|
||||||
rather than defining a subclass, you can specialise classes by partial
|
rather than defining a subclass, you can specialise classes by partial
|
||||||
application of the arguments to the constructor.
|
application of the arguments to the constructor.
|
||||||
|
|
||||||
|
@ -117,7 +124,8 @@ callbacks for Tkinter widgets on the fly::
|
||||||
c.pack()
|
c.pack()
|
||||||
|
|
||||||
for colour in sys.argv[1:]:
|
for colour in sys.argv[1:]:
|
||||||
b = Button(win, text=colour, command=partial(c.config,bg=colour))
|
b = Button(win, text=colour,
|
||||||
|
command=partial(c.config, bg=colour))
|
||||||
b.pack(side='left')
|
b.pack(side='left')
|
||||||
|
|
||||||
win.mainloop()
|
win.mainloop()
|
||||||
|
@ -129,16 +137,13 @@ Abandoned Syntax Proposal
|
||||||
I originally suggested the syntax ``fn@(*args, **kw)``, meaning the
|
I originally suggested the syntax ``fn@(*args, **kw)``, meaning the
|
||||||
same as ``partial(fn, *args, **kw)``.
|
same as ``partial(fn, *args, **kw)``.
|
||||||
|
|
||||||
At least there are no backwards-compatibility issues because the @
|
|
||||||
character isn't a legal operator in any previous versions of Python.
|
|
||||||
|
|
||||||
The @ sign is used in some assembly languages to imply register
|
The @ sign is used in some assembly languages to imply register
|
||||||
indirection, and the use here is also a kind of indirection.
|
indirection, and the use here is also a kind of indirection.
|
||||||
``f@(x)`` is not ``f(x)`` , but a thing that becomes ``f(x)`` when you
|
``f@(x)`` is not ``f(x)``, but a thing that becomes ``f(x)`` when you
|
||||||
call it.
|
call it.
|
||||||
|
|
||||||
It has not been well-received, so I have withdrawn this part of the
|
It was not well-received, so I have withdrawn this part of the
|
||||||
proposal.
|
proposal. In any case, @ has been taken for the new decorator syntax.
|
||||||
|
|
||||||
|
|
||||||
Feedback from comp.lang.python and python-dev
|
Feedback from comp.lang.python and python-dev
|
||||||
|
@ -199,12 +204,10 @@ Carl Banks posted an implementation as a real functional closure::
|
||||||
return fn(*(cargs + fargs), **d)
|
return fn(*(cargs + fargs), **d)
|
||||||
return call_fn
|
return call_fn
|
||||||
|
|
||||||
which he assures me is more efficient. You lose introspection and
|
which he assures me is more efficient.
|
||||||
sub-classing that way, but these are maybe only marginal benefits and
|
|
||||||
not worth a performance hit, so this would also do as a reference
|
|
||||||
implementation.
|
|
||||||
|
|
||||||
I also coded the class in Pyrex::
|
I also coded the class in Pyrex, to estimate how the performance
|
||||||
|
might be improved by coding it in C::
|
||||||
|
|
||||||
cdef class curry:
|
cdef class curry:
|
||||||
|
|
||||||
|
@ -241,7 +244,13 @@ implementation of ``partial``, and any other higher-order functions
|
||||||
the community want. Other functions that might belong there fall
|
the community want. Other functions that might belong there fall
|
||||||
outside the scope of this PEP though.
|
outside the scope of this PEP though.
|
||||||
|
|
||||||
The @ syntax proposal has been withrawn.
|
Patches for the implementation, documentation and unit tests (SF
|
||||||
|
patches 931005_, 931007_, and 931010_ respectively) have been
|
||||||
|
submitted but not yet checked in.
|
||||||
|
|
||||||
|
A C implementation by Hye-Shik Chang has also been submitted, although
|
||||||
|
it is not expected to be included until after the Python
|
||||||
|
implementation has proven itself useful enough to be worth optimising.
|
||||||
|
|
||||||
|
|
||||||
References
|
References
|
||||||
|
@ -249,6 +258,12 @@ References
|
||||||
|
|
||||||
.. [1] http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52549
|
.. [1] http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52549
|
||||||
|
|
||||||
|
.. [2] Patches 931005_, 931007_, and 931010_.
|
||||||
|
|
||||||
|
.. _931005: http://www.python.org/sf/931005
|
||||||
|
.. _931007: http://www.python.org/sf/931007
|
||||||
|
.. _931010: http://www.python.org/sf/931010
|
||||||
|
|
||||||
|
|
||||||
Copyright
|
Copyright
|
||||||
=========
|
=========
|
||||||
|
|
Loading…
Reference in New Issue