[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