[ python-Feature Requests-1706256 ] Give Partial the ability to skip positionals

SourceForge.net noreply at sourceforge.net
Thu Apr 26 06:14:04 CEST 2007


Feature Requests item #1706256, was opened at 2007-04-23 20:18
Message generated for change (Comment added) made by belopolsky
You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=355470&aid=1706256&group_id=5470

Please note that this message will contain a full copy of the comment thread,
including the initial issue submission, for this request,
not just the latest update.
Category: None
Group: None
Status: Open
Resolution: None
Priority: 5
Private: No
Submitted By: Calvin Spealman (ironfroggy)
Assigned to: Nobody/Anonymous (nobody)
Summary: Give Partial the ability to skip positionals

Initial Comment:
There are some situations where you want to skip positional arguments in a use of a partial function. In other words, you want to create a partial that applies positional arguments out of order or without applying values to one or more lower positional arguments. In some cases keyword arguments can be used instead, but this has two obvious drawbacks. Firstly, it causes the caller to rely on the name of a positional in a callee, which breaks encapsulation. Secondly, on the case of the function being applied to being a builtin, it fails completely, as they will not take positional arguments by name at all. I propose a class attribute to the partial type, 'skip', which will be a singleton to pass to a partial object signifying this skipping of positionals. The following example demonstrates.

from functools import partial

def add(a, b):
    return a + b

append_abc = partial(add, partial.skip, "abc")
assert append_abc("xyz") == "xyzabc"

Obviously this example would break if used as partial(add, b="abc") and the maintainer of add changed the positional names to 'first' and 'second' or 'pre' and 'post', which is perfectly reasonable. We do not need to expect the names of our positional arguments are depended upon. It would also break when someone gets smart and replaces the add function with operator.add, of course.

----------------------------------------------------------------------

Comment By: Alexander Belopolsky (belopolsky)
Date: 2007-04-26 00:14

Message:
Logged In: YES 
user_id=835142
Originator: NO

If you remove partial_type.tp_dict = PyDict_New(); at line 309, the patch
will pass test_functools.

A few comments:

Design:
1. partial.skip should be an instance of a singleton class (look at
NoneType implementation in object.c)
2. repr(partial.skip) should be 'functools.partial.skip' (easy to
implement once #1 is done)

Implementation:
1.  In the loop over pto->args you know that i < npargs, so you can use
PyTuple_GET_ITEM and there is no need to check for arg==NULL
2. You should check PyTuple_GetItem(args, pull_index) for null and return
with error if too few arguments is supplied.  Better yet, find number of
supplied args outside the loop and raise your own error if pool_index grows
to that number.
3. It looks like you are leaking references. I don't see where you decref
ptoargscopy and arg after concatenation.


----------------------------------------------------------------------

Comment By: Calvin Spealman (ironfroggy)
Date: 2007-04-26 00:10

Message:
Logged In: YES 
user_id=112166
Originator: YES

Hmm, I didn't get such an error here on VC with the extra argument. I'll
change that here, too.

I figured the breaking of the subclassing of partial was related to what I
do with tp_dict, but I don't understand how. How did I blow it up? And,
yes, I will write tests for the new functionality, of course.

----------------------------------------------------------------------

Comment By: Alexander Belopolsky (belopolsky)
Date: 2007-04-25 23:34

Message:
Logged In: YES 
user_id=835142
Originator: NO

OK, I've got it.  Your patch breaks test_functools.  This is because you
have blown up partial_type.tp_dict . 

----------------------------------------------------------------------

Comment By: Alexander Belopolsky (belopolsky)
Date: 2007-04-25 23:21

Message:
Logged In: YES 
user_id=835142
Originator: NO

The current patch does not compile:

Modules/_functoolsmodule.c: In function 'init_functools':
Modules/_functoolsmodule.c:306: error: too many arguments to function
'PyObject_CallObject'

Once I removed the extra NULL argument, it seems to work fine.  What
exactly is broken?  Can you add unit tests for the new functionality?

----------------------------------------------------------------------

Comment By: Calvin Spealman (ironfroggy)
Date: 2007-04-25 22:58

Message:
Logged In: YES 
user_id=112166
Originator: YES

If anyone has a serious argument against the partial.skip name, I would
take partial.unbound as my second choice, but I definitely prefer
partial.skip to it. Third would be partial.latebound. I still can't figure
out how my code broke subclassing of partial, so if anyone can take a look,
I'd appreciate it hugely.

----------------------------------------------------------------------

Comment By: Alexander Belopolsky (belopolsky)
Date: 2007-04-25 22:31

Message:
Logged In: YES 
user_id=835142
Originator: NO

Names I've seen used for this purpose elsewhere: slot, arg, missing.

----------------------------------------------------------------------

Comment By: Martin v. Löwis (loewis)
Date: 2007-04-24 01:41

Message:
Logged In: YES 
user_id=21627
Originator: NO

I would not call it partial.skip, but partial.unbound (or find yet a
better name that indicates that the argument is not skipped, but instead
will be an argument of the resulting partial function).

----------------------------------------------------------------------

Comment By: Calvin Spealman (ironfroggy)
Date: 2007-04-23 23:45

Message:
Logged In: YES 
user_id=112166
Originator: YES

File Added: partial_skip.patch

----------------------------------------------------------------------

You can respond by visiting: 
https://sourceforge.net/tracker/?func=detail&atid=355470&aid=1706256&group_id=5470


More information about the Python-bugs-list mailing list