GeezerVison is showing github.com — Invalid "equivalents" of the complex type constructor in docs · Issue #109218 · python/cpython
Invalid "equivalents" of the complex type constructor in docs #109218DescriptionThe sphinx docs says:
class complex(real=0, imag=0)
[...]
Return a complex number with the value real + imag*1j or convert a string or number to a complex number.
[...]
The docstring (btw it doesn't mention a string as an argument):
>>> print(complex.__doc__)
Create a complex number from a real part and an optional imaginary part.
This is equivalent to (real + imag*1j) where imag defaults to 0.
That wrong, e.g.:
>>> complex(0.0, -0.0)
-0j
>>> 0.0 + (-0.0)*1j
0j
>>> complex(-0.0, -0.0)
(-0-0j)
>>> -0.0 + (-0.0)*1j
(-0+0j)
>>> complex(-0.0, 0.0)
(-0+0j)
>>> -0.0 + 0.0*1j
0j
Here is an attempt (patch) to solve, let me know if this is worth a PR:
diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst
index d9974c6350..78b85658ef 100644
--- a/Doc/library/functions.rst
+++ b/Doc/library/functions.rst
@@ -373,8 +373,8 @@ are always available. They are listed here in alphabetical order.
.. class:: complex(real=0, imag=0)
complex(string)
- Return a complex number with the value *real* + *imag*\*1j or convert a string
- or number to a complex number. If the first parameter is a string, it will
+ Create a complex number from a real part and an optional imaginary part
+ or convert a string to a complex number. If the first parameter is a string, it will
be interpreted as a complex number and the function must be called without a
second parameter. The second parameter can never be a string. Each argument
may be any numeric type (including complex). If *imag* is omitted, it
diff --git a/Objects/complexobject.c b/Objects/complexobject.c
index 0e96f54584..336b703233 100644
--- a/Objects/complexobject.c
+++ b/Objects/complexobject.c
@@ -886,9 +886,8 @@ complex.__new__ as complex_new
real as r: object(c_default="NULL") = 0
imag as i: object(c_default="NULL") = 0
-Create a complex number from a real part and an optional imaginary part.
-
-This is equivalent to (real + imag*1j) where imag defaults to 0.
+Create a complex number from a real part and an optional imaginary part
+or convert a string to a complex number.
[clinic start generated code]*/
static PyObject *
Edit:
Another instance of this issue is in the cmath docs:
A Python complex number ``z`` is stored internally using *rectangular*
or *Cartesian* coordinates. It is completely determined by its *real
part* ``z.real`` and its *imaginary part* ``z.imag``. In other
words::
z == z.real + z.imag*1j
E.g.:
>>> from cmath import inf
>>> complex(0.0, inf)
infj
>>> 0.0 + inf*1j
(nan+infj)
Linked PRs
ActivityAA-Turner commented on Sep 10, 2023 mdickinson commented on Sep 11, 2023 Note that the two arguments to complex can themselves be complex numbers, so describing them as the real and imaginary part isn't always accurate:
>>> complex(1+2j, 1-2j)
(3+3j)
skirpichev commented on Sep 12, 2023
two arguments to complex can themselves be complex numbers
Indeed, but in this form the "equivalency" complex(r, i) == r + i*1j is also broken:
>>> complex(r := nan-infj, i := -inf+infj)
(nan-infj)
>>> r + i*1j
(nan+nanj)
>>> complex(r := -0.0-0j, i := 1+0j)
(-0+1j)
>>> r + i*1j
1j
Under the hood, instead, we have:
>>> complex(r.real - i.imag, i.real + r.imag)
(-0+1j)
describing them as the real and imaginary part isn't always accurate
It's used in the current docstring, anyway.
Lets decide, however, whether this is a bug, regardless from the outcome in the mentioned discussion. Or not (as for complex vs eval(repr(complex))). skirpichev commented on May 25, 2024 @mdickinson, does this looks as an issue for you or we should accept imprecise docs? I don't see good ways to reword docs, while keeping them short and expressive.
Not sure, if this is a good idea to revival the d.p.o thread. On another hand, mentioned in the d.p.o variant with the imaginary type isn't explored well. Here is an implementation of the imaginary type & mixed-mode arithmetic rules: skirpichev#1 Among others, that should address current issue.
@serhiy-storchaka, do you think that it worth to discuss this proposal as a PEP?
So far major arguments against were:
- (a) it’s a fairly large and involved change in comparison to the size of the problem it’s solving
- (b) adoption of the C99 imaginary types has been disappointing
I think that above implementation is more or less complete to estimate (a): so far most changes limited to arithmetic methods. (b) - this looks to be a strong one. On another hand, this feature of the C99+ standards is optional - that might be an explanation of partial adoption, while in the Python - complex arithmetic is a part of the language. For numeric C libraries, the GSL, for example, has own routines to do mixed-mode arithmetic... serhiy-storchaka commented on May 27, 2024 Currently the signature of complex is:
Both real and imag are positional-or-keyword parameters. This allows absurd calls like complex(real="1j").
I think that it should support several more limited signatures:
complex(number=0, /)
complex(string, /)
complex(real=0, imag=0)
A string and complex number arguments should only be passed as a positional argument. real and imag should only be real numbers. skirpichev commented on May 27, 2024 @serhiy-storchaka, yes I think this could solve the current issue like proposed in it's description. (I.e. we should remove all mentions of broken identities.)
At price of breaking compatibility. It seems, support for imaginary arguments exists since v2.2 (6d6c1a3). Not sure on what ground it was added, I doubt it's practically used.
This allows absurd calls like complex(real="1j").
... on another hand it might be viewed as a bug.
Shall I open a separate issue or it would be better to discuss this first on d.p.o? mdickinson commented on May 27, 2024
I think that it should support several more limited signatures:
+1. I'd particularly like to see the form complex(1 + 1j, 3 - 4j) deprecated, and eventually dropped. serhiy-storchaka commented on May 27, 2024 I think this is the right issue, and no need to open another issue. My plan:
- Document the current behavior more accurately (without focusing on passing a string as the "real" keyword argument). The docstring may be more brief and do not include weird cases. This change should be backported.
- Make passing a string as the "real" keyword argument an error. I do not think any deprecation is needed here. It looks like just an implementation artifact.
- Deprecate accepting complex numbers as "real" and "image" arguments. This is the old behavior, since introduction of the
complex() builtin in 1.4 (8a5c5d2), but I do not think there is a use case for this. Accepting a complex number as the "real" argument could be an implementation artifact, but I have no explanation for accepting a complex number as the "imag" argument.
#119620 implements the last two items. serhiy-storchaka commented on May 30, 2024 added a commit that references this issue on Oct 23, 2026gh-109218: announce removal of complex constructor deprecations in 3.…
MetadataMetadataDevelopmentNo branches or pull requestsIssue actions
|