# in-place exponentiation incongruities

Giacomo Alzetta giacomo.alzetta at gmail.com
Sun Aug 12 09:14:27 CEST 2012

```Il giorno domenica 12 agosto 2012 06:28:10 UTC+2, Steven D'Aprano ha scritto:
> On Sat, 11 Aug 2012 09:54:56 -0700, Giacomo Alzetta wrote:
>
>
>
> > I've noticed some incongruities regarding in-place exponentiation.
>
> >
>
> > On the C side nb_inplace_power is a ternary function, like nb_power (see
>
> > here:
>
> > http://docs.python.org/c-api/typeobj.html?
>
> highlight=numbermethods#PyNumberMethods).
>
> >
>
> > Obviously you can't pass the third argument using the usual in-place
>
> > syntax "**=". Nevertheless I'd expect to be able to provide the third
>
> > argument using operator.ipow. But the operator module accept only the
>
> > two parameter variant.
>
>
>
> Why? The operator module implements the ** operator, not the pow()
>
> function. If you want the pow() function, you can just use it directly,
>
> no need to use operator.pow or operator.ipow.
>
>
>
> Since ** is a binary operator, it can only accept two arguments.
>
>
>
>
>
> > The Number Protocol specify that the ipow operation ""is the equivalent
>
> > of the Python statement o1 **= o2 when o3 is Py_None, or an in-place
>
> > variant of pow(o1, o2, o3) otherwise.""
>
>
>
> Where is that from?
>
>
>
>
>
> --
>
> Steven

>From The Number Protocol(http://docs.python.org/c-api/number.html).
The full text is:

PyObject* PyNumber_InPlacePower(PyObject *o1, PyObject *o2, PyObject *o3)
Return value: New reference.

**See the built-in function pow().** Returns NULL on failure. The operation is done in-place when o1 supports it. This is the equivalent of the Python statement o1 **= o2 when o3 is Py_None, or an in-place variant of pow(o1, o2, o3) otherwise. If o3 is to be ignored, pass Py_None in its place (passing NULL for o3 would cause an illegal memory access).

The first thing that this text does is referring to the **function** pow, which takes three arguments. And since the documentation of the operator module states that "The operator module exports a set of efficient functions corresponding to the intrinsic operators of Python.", I'd expect the ipow to have three arguments, the third being optional.

With normal exponentiation you have ** referring to the 2-argument variant, and "pow" providing the ability to use the third argument.
At the moment in-place exponentiation you have "**=" referring to the 2-argument variant(and this is consistent), while operator.ipow also referring to it. So providing an ipow with the third argument would just increase consistency in the language, and provide a feature that at the moment is not present. (well if the designers of python care really much about consistency they'd probably add an "ipow" built-in function, so that you don't have to import it from "operator").

I understand that it's not a feature often used, but I can't see why not allowing it.
At the moment you can do that from the C side, because you can call PyNumber_InPlacePower directly, but from the python side you have no way to do that, except for writing a C-extension that wraps the PyNumber_InPlacePower function.

```