If you read the language reference for augmented arithmetic assignment, you
will note that it essentially says, "call __i<op>__, and if that doesn't
work call as if you were doing a <op> b". Unfortunately it appears **= does
not follow the rule of falling back on the binary arithmetic expression
semantics. I have a GitHub gist with demonstration code that shows this
happening in both 3.8 and master (
https://gist.github.com/brettcannon/fec4152857e0ed551b4da515dc63e580). This
was reported in https://bugs.python.org/issue38302, although initially it
didn't cover __pow__, only __rpow__ being skipped.

This appears to happen because the opcode  for **= calls
PyNumber_InPlacePower() (
https://github.com/python/cpython/blob/802726acf6048338394a6a4750835c2cdd6a947b/Objects/abstract.c#L1159)
which calls ternary_op for __ipow__ or __pow__ depending on which is
defined, but will never try both (
https://github.com/python/cpython/blob/802726acf6048338394a6a4750835c2cdd6a947b/Objects/abstract.c#L849).
All of the other augmented arithmetic assignment operators have a special
binary_iop() function to call which takes care of the fallback logic, so no
other augmented arithmetic assignments appear to have this problem (I
tested them all regardless).

I think there are two options to fixing this:

1. Add a note to the data model that **= is special and does not fall back
(obviously the most backwards-compatible)
2. Fix **= (which makes sense from a language consistency perspective)

Personally, my vote is for #2 as I don't want to have to remember that **=
is somehow special compared to all other augmented assignments. I also
don't think the backwards-compatibility risk is at all large since the
semantics of turning `a **= b` into `a = a ** b` shouldn't really be
different.

P.S. Why are some of the PyNumber_InPlace*() functions handwritten while
others are defined using a macro which mirrors the handwritten ones? Just
something I noticed while investigating this.
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/MJTHPFSHGH7RIEKXQKYUBHCZBW3T3JTR/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to