[Python-Dev] Fwd: summing a bunch of numbers (or "whatevers")

Tim Peters tim.one@comcast.net
Mon, 21 Apr 2003 17:31:20 -0400

[Raymond Hettinger]
> For the C implementation, consider bypassing operator.add
> and calling the nb_add slot directly.  It's faster and fulfills
> the intention to avoid the alternative call to sq_concat.

Checking for the existence of a (non-NULL) nb_add slot may be slicker than
special-casing strings, but I'm not sure it's ever going to work if we try
to call nb_add directly.  In the end, I expect we'd have to duplicate all
the logic in abstract.c's private binary_op1() to get all the endcases

  Calling scheme used for binary operations:

  v	w	Action
  new	new	w.op(v,w)[*], v.op(v,w), w.op(v,w)
  new	old	v.op(v,w), coerce(v,w), v.op(v,w)
  old	new	w.op(v,w), coerce(v,w), v.op(v,w)
  old	old	coerce(v,w), v.op(v,w)

  [*] only when v->ob_type != w->ob_type && w->ob_type is a subclass of

  * new == new style number
  * old == old style number
  * Action indicates the order in which operations are tried until either
    a valid result is produced or an error occurs.


OTOH, when the nb_add slot isn't NULL, the public PyNumber_Add (the same as
operator.add) will do no more than invoke binary_op1 (unless the nb_add slot
returns NotImplemented, which is another endcase you have to consider when
calling nb_add directly -- I believe the Python core calls nb_add directly
in only one place, when it already knows that both operands are ints, and
that their sum overflows an int, so wants long.__add__ to handle it).

> Also, think about whether you want to match to two argument
> styles for min() and max():
>   >>> max(1,2,3)
>   3
>   >>> max([1,2,3])
>   3

Guido already Pronounced on that -- max(x, y) is the clearest way to perform
that operation, but there's no point to making sum(x, y) an obscure way to
spell x+y (I suppose you want it as a builtin synonym for operator.add,
though <wink>).

> ...
> P.S.  Your new builtin works great with itertools.
>     def dotproduct(vec1, vec2):
>         return sum(itertools.imap(operator.mul, vec1, vec2))