summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2024-05-30 20:20:07 (GMT)
committerGitHub <noreply@github.com>2024-05-30 20:20:07 (GMT)
commitec1ba264607b2b7b98d2602f5536a1d02981efc6 (patch)
tree6803200390bd836aa0841cc5f35971fedcebef9f
parent1c04c63ced5038e8f45a2aac7dc45f0815a4ddc5 (diff)
downloadcpython-ec1ba264607b2b7b98d2602f5536a1d02981efc6.zip
cpython-ec1ba264607b2b7b98d2602f5536a1d02981efc6.tar.gz
cpython-ec1ba264607b2b7b98d2602f5536a1d02981efc6.tar.bz2
gh-109218: Improve documentation for the complex() constructor (GH-119687)
* Remove the equivalence with real+imag*1j which can be incorrect in corner cases (non-finite numbers, the sign of zeroes). * Separately document the three roles of the constructor: parsing a string, converting a number, and constructing a complex from components. * Document positional-only parameters of complex(), float(), int() and bool() as positional-only. * Add examples for complex() and int(). * Specify the grammar of the string for complex(). * Improve the grammar of the string for float(). * Describe more explicitly the behavior when real and/or imag arguments are complex numbers. (This will be deprecated in future.)
-rw-r--r--Doc/library/cmath.rst7
-rw-r--r--Doc/library/functions.rst173
-rw-r--r--Objects/clinic/complexobject.c.h9
-rw-r--r--Objects/complexobject.c9
4 files changed, 135 insertions, 63 deletions
diff --git a/Doc/library/cmath.rst b/Doc/library/cmath.rst
index 65e98e0..381a833 100644
--- a/Doc/library/cmath.rst
+++ b/Doc/library/cmath.rst
@@ -43,10 +43,7 @@ Conversions to and from polar coordinates
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
+part* ``z.real`` and its *imaginary part* ``z.imag``.
*Polar coordinates* give an alternative way to represent a complex
number. In polar coordinates, a complex number *z* is defined by the
@@ -90,7 +87,7 @@ rectangular coordinates to polar coordinates and back.
.. function:: rect(r, phi)
Return the complex number *x* with polar coordinates *r* and *phi*.
- Equivalent to ``r * (math.cos(phi) + math.sin(phi)*1j)``.
+ Equivalent to ``complex(r * math.cos(phi), r * math.sin(phi))``.
Power and logarithmic functions
diff --git a/Doc/library/functions.rst b/Doc/library/functions.rst
index cb9b650..c07b104 100644
--- a/Doc/library/functions.rst
+++ b/Doc/library/functions.rst
@@ -141,10 +141,11 @@ are always available. They are listed here in alphabetical order.
See also :func:`format` for more information.
-.. class:: bool(x=False)
+.. class:: bool(object=False, /)
- Return a Boolean value, i.e. one of ``True`` or ``False``. *x* is converted
- using the standard :ref:`truth testing procedure <truth>`. If *x* is false
+ Return a Boolean value, i.e. one of ``True`` or ``False``. The argument
+ is converted using the standard :ref:`truth testing procedure <truth>`.
+ If the argument is false
or omitted, this returns ``False``; otherwise, it returns ``True``. The
:class:`bool` class is a subclass of :class:`int` (see :ref:`typesnumeric`).
It cannot be subclassed further. Its only instances are ``False`` and
@@ -153,7 +154,7 @@ are always available. They are listed here in alphabetical order.
.. index:: pair: Boolean; type
.. versionchanged:: 3.7
- *x* is now a positional-only parameter.
+ The parameter is now positional-only.
.. function:: breakpoint(*args, **kws)
@@ -371,29 +372,73 @@ are always available. They are listed here in alphabetical order.
support for top-level ``await``, ``async for``, and ``async with``.
-.. class:: complex(real=0, imag=0)
- complex(string)
+.. class:: complex(number=0, /)
+ complex(string, /)
+ complex(real=0, imag=0)
+
+ Convert a single string or number to a complex number, or create a
+ complex number from real and imaginary parts.
+
+ Examples:
+
+ .. doctest::
+
+ >>> complex('+1.23')
+ (1.23+0j)
+ >>> complex('-4.5j')
+ -4.5j
+ >>> complex('-1.23+4.5j')
+ (-1.23+4.5j)
+ >>> complex('\t( -1.23+4.5J )\n')
+ (-1.23+4.5j)
+ >>> complex('-Infinity+NaNj')
+ (-inf+nanj)
+ >>> complex(1.23)
+ (1.23+0j)
+ >>> complex(imag=-4.5)
+ -4.5j
+ >>> complex(-1.23, 4.5)
+ (-1.23+4.5j)
+
+ If the argument is a string, it must contain either a real part (in the
+ same format as for :func:`float`) or an imaginary part (in the same
+ format but with a ``'j'`` or ``'J'`` suffix), or both real and imaginary
+ parts (the sign of the imaginary part is mandatory in this case).
+ The string can optionally be surrounded by whitespaces and the round
+ parentheses ``'('`` and ``')'``, which are ignored.
+ The string must not contain whitespace between ``'+'``, ``'-'``, the
+ ``'j'`` or ``'J'`` suffix, and the decimal number.
+ For example, ``complex('1+2j')`` is fine, but ``complex('1 + 2j')`` raises
+ :exc:`ValueError`.
+ More precisely, the input must conform to the :token:`~float:complexvalue`
+ production rule in the following grammar, after parentheses and leading and
+ trailing whitespace characters are removed:
- 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
- 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
- defaults to zero and the constructor serves as a numeric conversion like
- :class:`int` and :class:`float`. If both arguments are omitted, returns
- ``0j``.
+ .. productionlist:: float
+ complexvalue: `floatvalue` |
+ : `floatvalue` ("j" | "J") |
+ : `floatvalue` `sign` `absfloatvalue` ("j" | "J")
+ If the argument is a number, the constructor serves as a numeric
+ conversion like :class:`int` and :class:`float`.
For a general Python object ``x``, ``complex(x)`` delegates to
- ``x.__complex__()``. If :meth:`~object.__complex__` is not defined then it falls back
- to :meth:`~object.__float__`. If :meth:`!__float__` is not defined then it falls back
+ ``x.__complex__()``.
+ If :meth:`~object.__complex__` is not defined then it falls back
+ to :meth:`~object.__float__`.
+ If :meth:`!__float__` is not defined then it falls back
to :meth:`~object.__index__`.
- .. note::
+ If two arguments are provided or keyword arguments are used, each argument
+ may be any numeric type (including complex).
+ If both arguments are real numbers, return a complex number with the real
+ component *real* and the imaginary component *imag*.
+ If both arguments are complex numbers, return a complex number with the real
+ component ``real.real-imag.imag`` and the imaginary component
+ ``real.imag+imag.real``.
+ If one of arguments is a real number, only its real component is used in
+ the above expressions.
- When converting from a string, the string must not contain whitespace
- around the central ``+`` or ``-`` operator. For example,
- ``complex('1+2j')`` is fine, but ``complex('1 + 2j')`` raises
- :exc:`ValueError`.
+ If all arguments are omitted, returns ``0j``.
The complex type is described in :ref:`typesnumeric`.
@@ -682,21 +727,38 @@ are always available. They are listed here in alphabetical order.
elements of *iterable* for which *function* is false.
-.. class:: float(x=0.0)
+.. class:: float(number=0.0, /)
+ float(string, /)
.. index::
single: NaN
single: Infinity
- Return a floating point number constructed from a number or string *x*.
+ Return a floating point number constructed from a number or a string.
+
+ Examples:
+
+ .. doctest::
+
+ >>> float('+1.23')
+ 1.23
+ >>> float(' -12345\n')
+ -12345.0
+ >>> float('1e-003')
+ 0.001
+ >>> float('+1E6')
+ 1000000.0
+ >>> float('-Infinity')
+ -inf
If the argument is a string, it should contain a decimal number, optionally
preceded by a sign, and optionally embedded in whitespace. The optional
sign may be ``'+'`` or ``'-'``; a ``'+'`` sign has no effect on the value
produced. The argument may also be a string representing a NaN
- (not-a-number), or positive or negative infinity. More precisely, the
- input must conform to the ``floatvalue`` production rule in the following
- grammar, after leading and trailing whitespace characters are removed:
+ (not-a-number), or positive or negative infinity.
+ More precisely, the input must conform to the :token:`~float:floatvalue`
+ production rule in the following grammar, after leading and trailing
+ whitespace characters are removed:
.. productionlist:: float
sign: "+" | "-"
@@ -705,9 +767,10 @@ are always available. They are listed here in alphabetical order.
digit: <a Unicode decimal digit, i.e. characters in Unicode general category Nd>
digitpart: `digit` (["_"] `digit`)*
number: [`digitpart`] "." `digitpart` | `digitpart` ["."]
- exponent: ("e" | "E") ["+" | "-"] `digitpart`
- floatnumber: number [`exponent`]
- floatvalue: [`sign`] (`floatnumber` | `infinity` | `nan`)
+ exponent: ("e" | "E") [`sign`] `digitpart`
+ floatnumber: `number` [`exponent`]
+ absfloatvalue: `floatnumber` | `infinity` | `nan`
+ floatvalue: [`sign`] `absfloatvalue`
Case is not significant, so, for example, "inf", "Inf", "INFINITY", and
"iNfINity" are all acceptable spellings for positive infinity.
@@ -723,26 +786,13 @@ are always available. They are listed here in alphabetical order.
If no argument is given, ``0.0`` is returned.
- Examples::
-
- >>> float('+1.23')
- 1.23
- >>> float(' -12345\n')
- -12345.0
- >>> float('1e-003')
- 0.001
- >>> float('+1E6')
- 1000000.0
- >>> float('-Infinity')
- -inf
-
The float type is described in :ref:`typesnumeric`.
.. versionchanged:: 3.6
Grouping digits with underscores as in code literals is allowed.
.. versionchanged:: 3.7
- *x* is now a positional-only parameter.
+ The parameter is now positional-only.
.. versionchanged:: 3.8
Falls back to :meth:`~object.__index__` if :meth:`~object.__float__` is not defined.
@@ -926,17 +976,36 @@ are always available. They are listed here in alphabetical order.
with the result after successfully reading input.
-.. class:: int(x=0)
- int(x, base=10)
+.. class:: int(number=0, /)
+ int(string, /, base=10)
+
+ Return an integer object constructed from a number or a string, or return
+ ``0`` if no arguments are given.
+
+ Examples:
+
+ .. doctest::
+
+ >>> int(123.45)
+ 123
+ >>> int('123')
+ 123
+ >>> int(' -12_345\n')
+ -12345
+ >>> int('FACE', 16)
+ 64206
+ >>> int('0xface', 0)
+ 64206
+ >>> int('01110011', base=2)
+ 115
- Return an integer object constructed from a number or string *x*, or return
- ``0`` if no arguments are given. If *x* defines :meth:`~object.__int__`,
- ``int(x)`` returns ``x.__int__()``. If *x* defines :meth:`~object.__index__`,
- it returns ``x.__index__()``. If *x* defines :meth:`~object.__trunc__`,
+ If the argument defines :meth:`~object.__int__`,
+ ``int(x)`` returns ``x.__int__()``. If the argument defines :meth:`~object.__index__`,
+ it returns ``x.__index__()``. If the argument defines :meth:`~object.__trunc__`,
it returns ``x.__trunc__()``.
For floating point numbers, this truncates towards zero.
- If *x* is not a number or if *base* is given, then *x* must be a string,
+ If the argument is not a number or if *base* is given, then it must be a string,
:class:`bytes`, or :class:`bytearray` instance representing an integer
in radix *base*. Optionally, the string can be preceded by ``+`` or ``-``
(with no space in between), have leading zeros, be surrounded by whitespace,
@@ -966,7 +1035,7 @@ are always available. They are listed here in alphabetical order.
Grouping digits with underscores as in code literals is allowed.
.. versionchanged:: 3.7
- *x* is now a positional-only parameter.
+ The first parameter is now positional-only.
.. versionchanged:: 3.8
Falls back to :meth:`~object.__index__` if :meth:`~object.__int__` is not defined.
@@ -977,7 +1046,7 @@ are always available. They are listed here in alphabetical order.
.. versionchanged:: 3.11
:class:`int` string inputs and string representations can be limited to
help avoid denial of service attacks. A :exc:`ValueError` is raised when
- the limit is exceeded while converting a string *x* to an :class:`int` or
+ the limit is exceeded while converting a string to an :class:`int` or
when converting an :class:`int` into a string would exceed the limit.
See the :ref:`integer string conversion length limitation
<int_max_str_digits>` documentation.
diff --git a/Objects/clinic/complexobject.c.h b/Objects/clinic/complexobject.c.h
index 49b5030..46c3b35 100644
--- a/Objects/clinic/complexobject.c.h
+++ b/Objects/clinic/complexobject.c.h
@@ -94,9 +94,12 @@ PyDoc_STRVAR(complex_new__doc__,
"complex(real=0, imag=0)\n"
"--\n"
"\n"
-"Create a complex number from a real part and an optional imaginary part.\n"
+"Create a complex number from a string or numbers.\n"
"\n"
-"This is equivalent to (real + imag*1j) where imag defaults to 0.");
+"If a string is given, parse it as a complex number.\n"
+"If a single number is given, convert it to a complex number.\n"
+"If the \'real\' or \'imag\' arguments are given, create a complex number\n"
+"with the specified real and imaginary components.");
static PyObject *
complex_new_impl(PyTypeObject *type, PyObject *r, PyObject *i);
@@ -157,4 +160,4 @@ skip_optional_pos:
exit:
return return_value;
}
-/*[clinic end generated code: output=04e6261649967b30 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=295ecfd71389d7fe input=a9049054013a1b77]*/
diff --git a/Objects/complexobject.c b/Objects/complexobject.c
index 943c5cc..17ee437 100644
--- a/Objects/complexobject.c
+++ b/Objects/complexobject.c
@@ -911,14 +911,17 @@ 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.
+Create a complex number from a string or numbers.
-This is equivalent to (real + imag*1j) where imag defaults to 0.
+If a string is given, parse it as a complex number.
+If a single number is given, convert it to a complex number.
+If the 'real' or 'imag' arguments are given, create a complex number
+with the specified real and imaginary components.
[clinic start generated code]*/
static PyObject *
complex_new_impl(PyTypeObject *type, PyObject *r, PyObject *i)
-/*[clinic end generated code: output=b6c7dd577b537dc1 input=f4c667f2596d4fd1]*/
+/*[clinic end generated code: output=b6c7dd577b537dc1 input=ff4268dc540958a4]*/
{
PyObject *tmp;
PyNumberMethods *nbr, *nbi = NULL;