msg84181 - (view) |
Author: Marek Kubica (leonidas) |
Date: 2009-03-26 15:48 |
When calling operators from the ``operator``-module, they refuse to accept keyword arguments: operator.add(a=1, b=2) TypeError: add() takes no keyword arguments Operators with keyword arguments are important when one wants to create partial functions with non-positional arguments. Take for example ``operator.mod`` where the order of the arguments matters: This works: map(lambda x: x % 2, range(5)) This does not work, since ``operator.mod`` does not support keyword arguments: map(functools.partial(operator.mod, b=2), range(5)) So there are two solutions: define one's own add(), mod(), contains() etc. but then the ``operator`` module is rather useless or make them accept keyword arguments. With ``partial`` in the Stdlib this solution would be a whole lot nicer. |
|
|
msg84189 - (view) |
Author: Raymond Hettinger (rhettinger) *  |
Date: 2009-03-26 17:27 |
Sounds like what you're really looking for is a version of partial() that lets you bind positional arguments in any position. Something like: partial(operator.mod, (1,2)) that pre-binds 2 to argument position 1. Changing the language to match the existing partial() function instead of changing partial() to fit the language seems like "the tail wagging the dog". FWIW, I don't think partial actually buys you anything useful. It's implementation isn't as flexible as a lambda, nor is it any faster. I think it mainly serves those who have an aversion to lambda, perhaps because of its name. Also, I don't think it's a good idea to assign arbitrary keywords to the operator functions unless those keywords have some meaning that makes programs more readable. The names "a" and "b" are only mildly useful a position placeholders. Names like "divisor" and "dividend" are more descriptive, but that is overkill. Overall, am -1 on the proposal. |
|
|
msg84192 - (view) |
Author: Marek Kubica (leonidas) |
Date: 2009-03-26 17:41 |
Well, some Schemes have an CURRYR variant which creates partial functions with positional arguments from the right but the current solution with partial accepting keywords is way more flexible since I can pre-set any arguments I like in such a function in any order. Doing so by using keyword arguments looks cleaner than by using the position of the argument. Compare ``partial(operator.mod, (2, 2))`` with ``partial(operator.mod, divisor=2)`` and at least to me, it is clearer what is happening in the second case. Even ``partial(operator.mod, b=2)`` looks simpler, albeit the name ``b`` is not particularly descriptive. The names ``a`` and ``b`` as used in many operators are indeed not very useful but renaming them wouldn't be a problem since nobody currently depends on ``a`` or ``b`` in their code; just in the order. That said, ``a`` and ``b`` are not so bad actually, because I couldn't think of better names for ``a`` and ``b`` in ``operator.contains(a, b)``. The nice thing now is, that partial can indeed replace many lambdas so not allowing partial to use operator seems just a random restriction. |
|
|
msg85093 - (view) |
Author: Raymond Hettinger (rhettinger) *  |
Date: 2009-04-01 21:03 |
Sorry, it makes no sense to me to add keyword arguments everywhere just to accommodate partial(). The alternative using lambda is workable and there have been proposals to further build-out partial. I acknowledge your distaste for lambda but it is firmly a part of the language and we aren't compelled to have to provide an alternative formulation for every possible lambda use case. In the case of the operator module, many of the functions do not have a natural set of names and so they should remain nameless -- there is not reason to prefer add(a,b) over add(p,q) or add(i,j) or add(x,y) -- none of those add any explanatory value to the reader and are fluff at best and hazardous at worst (for non-commutative binary operations when a letter can be reasonably assumed to be either of the two arguments). |
|
|