This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author josh.r
Recipients josh.r
Date 2016-10-06.21:18:27
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1475788708.75.0.957253302294.issue28381@psf.upfronthosting.co.za>
In-reply-to
Content
Not sure if this is the right venue to propose this, but I'd like to propose adding a starcaller method to the standard library, either functools or operator (not sure if the proposal is more like partial or more like methodcaller).

Basically, right now, when you want to take an existing function and call it repeatedly with preconstructed tuples using functional tools (e.g. sorted or groupby's key argument, multiprocessing.Pool's various map-like methods), you need to either have a special starmethod (e.g. Pool.map vs. Pool.starmap), or if Python doesn't provide one, you need use Python-defined functions (and for stuff like Pool, you can't even use lambda due to pickling issues, so you need to define the utility somewhere else). This means that you can't reuse builtins for stuff like the old "find runs of consecutive numbers" example from the itertools docs ( https://docs.python.org/2.6/library/itertools.html#examples ).

In terms of behavior:

    starfunc = starcaller(func)

would be behave roughly the same as the following (less efficient) Python 2 code:

    starfunc = functools.partial(apply, func)

(and perhaps starcaller(func, kwonly=True) would behave like functools.partial(apply, func, ()) to extend it to dicts).

This would make it possible to write the old consecutive numbers example:

    for k, g in groupby(enumerate(data), lambda (i,x):i-x):

(which is no longer legal since Py3 banned sequence unpacking in arguments like that) as:

    for k, g in groupby(enumerate(data), starcaller(operator.sub)):

It would also mean that instead of constantly needing to write new "star methods", you can just reuse existing functions with new batteries. For example, multiprocessing.Pool has a map and starmap function, but imap and imap_unordered have no starimap or starimap_unordered equivalents, which means using them at all requires you to def a function at trivial wrapper at global scope (possibly a long way away from the point of use) just to use an existing function ( def whydidineedthis(args): return existingfunction(*args) ).

With starcaller, there is no need to add starimap and friends, because the same result is easily achieved with:

    with multiprocessing.Pool() as pool:
        for res in pool.imap(starcaller(existingfunction), ...):

Is this a reasonable proposal? I could get an implementation ready fairly quickly, I'd just need to feedback on the name, which module it should be put in (functools or operator seem equally plausible) and whether the idea of using a keyword argument to the constructor makes more sense (kwonly=True) vs. expecting users to do functools.partial(starcaller(existingfunc), ()), vs. a separate class like doublestarcaller.
History
Date User Action Args
2016-10-06 21:18:28josh.rsetrecipients: + josh.r
2016-10-06 21:18:28josh.rsetmessageid: <1475788708.75.0.957253302294.issue28381@psf.upfronthosting.co.za>
2016-10-06 21:18:28josh.rlinkissue28381 messages
2016-10-06 21:18:27josh.rcreate