[Python-Dev] return type of __complex__

Steven D'Aprano steve at pearwood.info
Sun Oct 21 03:53:10 CEST 2012


On 21/10/12 06:28, Tres Seaver wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> On 10/19/2012 07:35 PM, Greg Ewing wrote:
>> Antonio Cuni wrote:
>>> Traceback (most recent call last): File "<stdin>", line 1, in
>>> <module>  TypeError: __complex__ should return a complex object
>>>
>>> i.e., the complex constructor does not check that __complex__
>>> returns an actual complex, while the cmath functions do.
>>
>> Looks to me like cmath is being excessively finicky here. Why
>> shouldn't a float be usable in *any* context expecting a complex?
>
> Exactly:  float is perfectly Liskov-substituable for complex;  only
> applications which do explicit type sniffing can tell the difference,
> which makes the sniffing bogus.


But float is not *numerically* substitutable for complex, which is why
type-sniffing is not bogus at all. If you have an application which
assumes numeric quantities represent real values, then you need to
distinguish between real-valued and complex-valued arithmetic, and
treating floats as implicitly complex is the wrong thing to do.

Since most applications are based on real-values, implicit promotion to
complex is in my opinion an anti-feature.

Python 2.x legitimately distinguished between floats and complex, e.g.:

py> (-100.0)**0.5
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
ValueError: negative number cannot be raised to a fractional power

If you wanted a complex result, you can explicitly ask for one:

py> (-100.0+0j)**0.5
(6.123031769111886e-16+10j)


I see that behaviour is changed in Python 3. Was this discussed before
being changed? I see a single sample docstring buried in PEP 3141 that:

"""a**b; should promote to float or complex when necessary."""

but I can't find any discussion of the consequences of this for the
majority of users who would be surprised by the unexpected appearance
of a "j" inside their numbers.

Nor is there any hint in the docs for pow and ** that they will promote
floats to complex:

http://docs.python.org/dev/library/functions.html#pow

http://docs.python.org/dev/library/stdtypes.html#numeric-types-int-float-complex



-- 
Steven


More information about the Python-Dev mailing list