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/802726acf6048338394a6a4750835c2cdd6a9...) which calls ternary_op for __ipow__ or __pow__ depending on which is defined, but will never try both ( https://github.com/python/cpython/blob/802726acf6048338394a6a4750835c2cdd6a9...). 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.