[Python-Dev] return type of __complex__

Steven D'Aprano steve at pearwood.info
Mon Oct 22 06:35:08 CEST 2012


On Mon, Oct 22, 2012 at 02:25:45PM +1100, Chris Angelico wrote:

> There really aren't that many situations where a program will be
> completely oblivious of complex/imaginary numbers and be able to
> encounter them... are there?

Fortunately the math module does not promote float to complex:

py> math.asin(2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: math domain error

(although the error message could be a bit nicer...)

so as far as I can tell, the only way you could accidentally get a 
complex number without expecting one is by exponentiation, either by ** 
or the builtin pow. This includes square roots. Exponentiation isn't as 
common as the basic four arithmetic operators, but it is hardly exotic.

Any time you have a non-integer power and a negative base, you will get 
a complex number. So there are two error conditions which used to give 
an exception but now promote to complex:

- taking the root (square root, cube root, etc.) of a number which 
  should be positive, but accidentally becomes negative (perhaps due to
  round-off error, you get a small -ve number instead of zero);

- the base may legitimately be negative, and the exponent is supposed
  to be a positive integer but accidentally because non-integral.

I suppose as someone who is rather fond of complex numbers, I should be 
pleased about this change, which raises the profile of complex and makes 
it closer to a "first class" numeric type. But my concern is that people 
who never dreamed that complex numbers even existed suddenly need to 
beware of them, and write LBYL code to avoid them, rather than relying 
on Python raising an exception.

In a nutshell, the semantics of ** have changed between 2.x and 3.x, and 
that's going to have consequences when porting code from 2 to 3. Perhaps 
2to3 needs to warn about the use of ** and pow?

[wishful thinking]
If we had floating point contexts, we could just tell people to stick 

import float
float.context.promote_to_complex = False

at the top of their module and they'd be fine.


-- 
Steven


More information about the Python-Dev mailing list