From 06fa57779baa3a8735ffbec70b95f9332198db08 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Wed, 7 May 2025 17:58:43 +0200 Subject: [PATCH 1/7] Reword the Integer literals section --- Doc/reference/expressions.rst | 3 +- Doc/reference/lexical_analysis.rst | 93 +++++++++++++++++++++--------- 2 files changed, 68 insertions(+), 28 deletions(-) diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index 2a550b504ca765..f6ea52956dc684 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -134,8 +134,7 @@ Literals Python supports string and bytes literals and various numeric literals: .. productionlist:: python-grammar - literal: `stringliteral` | `bytesliteral` - : | `integer` | `floatnumber` | `imagnumber` + literal: `stringliteral` | `bytesliteral` | `NUMBER` Evaluation of a literal yields an object of the given type (string, bytes, integer, floating-point number, complex number) with the given value. The value diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index b22eb4db7945d1..22766dd4a683bf 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -922,14 +922,24 @@ Numeric literals floating-point literal, hexadecimal literal octal literal, binary literal, decimal literal, imaginary literal, complex literal -There are three types of numeric literals: integers, floating-point numbers, and -imaginary numbers. There are no complex literals (complex numbers can be formed -by adding a real number and an imaginary number). +:token:`NUMBER` tokens represent numeric literals, of which there are three +types: integers, floating-point numbers, and imaginary numbers. + +.. grammar-snippet:: + :group: python-grammar + + NUMBER: integer | floatnumber | imagnumber + Note that numeric literals do not include a sign; a phrase like ``-1`` is actually an expression composed of the unary operator '``-``' and the literal ``1``. +Similarly, there are no complex literals; a phrase like ``1+2j`` is an +expression composed by the :ref:`integer literal ` ``1``, +the :ref:`operator ` '``+``', +and the :ref:`imaginary literal ` ``2j``. + .. index:: single: 0b; integer literal @@ -942,36 +952,67 @@ actually an expression composed of the unary operator '``-``' and the literal Integer literals ---------------- -Integer literals are described by the following lexical definitions: +Integer literals denote whole numbers. For example:: -.. productionlist:: python-grammar - integer: `decinteger` | `bininteger` | `octinteger` | `hexinteger` - decinteger: `nonzerodigit` (["_"] `digit`)* | "0"+ (["_"] "0")* - bininteger: "0" ("b" | "B") (["_"] `bindigit`)+ - octinteger: "0" ("o" | "O") (["_"] `octdigit`)+ - hexinteger: "0" ("x" | "X") (["_"] `hexdigit`)+ - nonzerodigit: "1"..."9" - digit: "0"..."9" - bindigit: "0" | "1" - octdigit: "0"..."7" - hexdigit: `digit` | "a"..."f" | "A"..."F" + 7 + 3 + 2147483647 There is no limit for the length of integer literals apart from what can be -stored in available memory. +stored in available memory:: + + 7922816251426433759354395033679228162514264337593543950336 + +Underscores can be used to group digits for enhanced readability, +and are ignored for determining the numeric value of the literal. +For example, the following literals are equivalent: -Underscores are ignored for determining the numeric value of the literal. They -can be used to group digits for enhanced readability. One underscore can occur -between digits, and after base specifiers like ``0x``. + 100_000_000_000 + 100000000000 + 1_00_00_00_00_000 -Note that leading zeros in a non-zero decimal number are not allowed. This is -for disambiguation with C-style octal literals, which Python used before version -3.0. +Underscores can only occur between digits. +For example, ``_123``, ``321_``, and ``123__321`` are *not* valid literals. -Some examples of integer literals:: +Integers can be specified in binary (base 2), octal (base 2), or hexadecimal +(base 16) using the prefixes ``0b``, ``0o`` and ``0x``, respectively. +Hexadecimal digits 10 through 15 are represented by letters ``A``-``F``, +case-insensitive. For example:: - 7 2147483647 0o177 0b100110111 - 3 79228162514264337593543950336 0o377 0xdeadbeef - 100_000_000_000 0b_1110_0101 + 0b100110111 + 0b_1110_0101 + 0o177 + 0o377 + 0xdeadbeef + 0xDead_Beef + +Underscores can occur between digits or after the base specifier, but not +within it. + +For example, ``0x_1f`` is a valid literal, but ``0_x1f`` is not. + +Note that leading zeros in a non-zero decimal number are not allowed. +For example, ``0123`` is not a valid literal. +This is for disambiguation with C-style octal literals, which Python used +before version 3.0. + +Formally, integer literals are described by the following lexical definitions: + +.. grammar-snippet:: + :group: python-grammar + + integer: `decinteger` | `bininteger` | `octinteger` | + `hexinteger` | `zerointeger` + decinteger: `nonzerodigit` (["_"] `digit`)* + bininteger: "0" ("b" | "B") (["_"] `bindigit`)+ + octinteger: "0" ("o" | "O") (["_"] `octdigit`)+ + hexinteger: "0" ("x" | "X") (["_"] `hexdigit`)+ + zerointeger: "0"+ (["_"] "0")* + nonzerodigit: "1"..."9" + digit: "0"..."9" + bindigit: "0" | "1" + octdigit: "0"..."7" + hexdigit: `digit` | "a"..."f" | "A"..."F" .. versionchanged:: 3.6 Underscores are now allowed for grouping purposes in literals. From f9d7d12a210995a5ae4264b2720a9459383c9c4a Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Wed, 7 May 2025 18:04:34 +0200 Subject: [PATCH 2/7] Fix-ups --- Doc/reference/lexical_analysis.rst | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index 22766dd4a683bf..2114e3b157130d 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -922,13 +922,13 @@ Numeric literals floating-point literal, hexadecimal literal octal literal, binary literal, decimal literal, imaginary literal, complex literal -:token:`NUMBER` tokens represent numeric literals, of which there are three -types: integers, floating-point numbers, and imaginary numbers. +:data:`~token.NUMBER` tokens represent numeric literals, of which there are +three types: integers, floating-point numbers, and imaginary numbers. .. grammar-snippet:: :group: python-grammar - NUMBER: integer | floatnumber | imagnumber + NUMBER: `integer` | `floatnumber` | `imagnumber` Note that numeric literals do not include a sign; a phrase like ``-1`` is @@ -965,7 +965,7 @@ stored in available memory:: Underscores can be used to group digits for enhanced readability, and are ignored for determining the numeric value of the literal. -For example, the following literals are equivalent: +For example, the following literals are equivalent:: 100_000_000_000 100000000000 @@ -974,7 +974,7 @@ For example, the following literals are equivalent: Underscores can only occur between digits. For example, ``_123``, ``321_``, and ``123__321`` are *not* valid literals. -Integers can be specified in binary (base 2), octal (base 2), or hexadecimal +Integers can be specified in binary (base 2), octal (base 8), or hexadecimal (base 16) using the prefixes ``0b``, ``0o`` and ``0x``, respectively. Hexadecimal digits 10 through 15 are represented by letters ``A``-``F``, case-insensitive. For example:: @@ -988,7 +988,6 @@ case-insensitive. For example:: Underscores can occur between digits or after the base specifier, but not within it. - For example, ``0x_1f`` is a valid literal, but ``0_x1f`` is not. Note that leading zeros in a non-zero decimal number are not allowed. @@ -1001,8 +1000,7 @@ Formally, integer literals are described by the following lexical definitions: .. grammar-snippet:: :group: python-grammar - integer: `decinteger` | `bininteger` | `octinteger` | - `hexinteger` | `zerointeger` + integer: `decinteger` | `bininteger` | `octinteger` | `hexinteger` | `zerointeger` decinteger: `nonzerodigit` (["_"] `digit`)* bininteger: "0" ("b" | "B") (["_"] `bindigit`)+ octinteger: "0" ("o" | "O") (["_"] `octdigit`)+ From 077448ee6acd6ca326ebc9b15800600bf5f6e0f0 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Wed, 7 May 2025 18:13:29 +0200 Subject: [PATCH 3/7] More fixups --- Doc/reference/lexical_analysis.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index 2114e3b157130d..af0f6055f87273 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -986,11 +986,11 @@ case-insensitive. For example:: 0xdeadbeef 0xDead_Beef -Underscores can occur between digits or after the base specifier, but not -within it. -For example, ``0x_1f`` is a valid literal, but ``0_x1f`` is not. +An underscore can follow the base specifier. +For example, ``0x_1f`` is a valid literal, but ``0_x1f`` and ``0x__1f`` are +not. -Note that leading zeros in a non-zero decimal number are not allowed. +Leading zeros in a non-zero decimal number are not allowed. For example, ``0123`` is not a valid literal. This is for disambiguation with C-style octal literals, which Python used before version 3.0. From ad9ab6356612adbce8033df54255ffb537411213 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Wed, 14 May 2025 16:18:19 +0200 Subject: [PATCH 4/7] Shorten `1+2j` --- Doc/reference/lexical_analysis.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index af0f6055f87273..b017aab5160397 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -935,8 +935,8 @@ Note that numeric literals do not include a sign; a phrase like ``-1`` is actually an expression composed of the unary operator '``-``' and the literal ``1``. -Similarly, there are no complex literals; a phrase like ``1+2j`` is an -expression composed by the :ref:`integer literal ` ``1``, +Similarly, there are no complex literals; the expression ``1+2j`` is composed +of the :ref:`integer literal ` ``1``, the :ref:`operator ` '``+``', and the :ref:`imaginary literal ` ``2j``. From 4916defc4337551f39820b837126ae23b85567b6 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Wed, 14 May 2025 18:21:15 +0200 Subject: [PATCH 5/7] Reword float literals --- Doc/reference/datamodel.rst | 2 + Doc/reference/lexical_analysis.rst | 72 ++++++++++++++++++++++-------- 2 files changed, 56 insertions(+), 18 deletions(-) diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 32a2e266262c52..4a099e81daccb3 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -262,6 +262,8 @@ Booleans (:class:`bool`) a string, the strings ``"False"`` or ``"True"`` are returned, respectively. +.. _datamodel-float: + :class:`numbers.Real` (:class:`float`) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index b017aab5160397..54d61949dc1352 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -930,8 +930,12 @@ three types: integers, floating-point numbers, and imaginary numbers. NUMBER: `integer` | `floatnumber` | `imagnumber` +The numeric value of a numeric literal is the same as if it were passed as a +string to the :class:`int`, :class:`float` or :class:`complex` class +constructor, respectively. +Note that not all valid inputs for those constructors are also valid literals. -Note that numeric literals do not include a sign; a phrase like ``-1`` is +Numeric literals do not include a sign; a phrase like ``-1`` is actually an expression composed of the unary operator '``-``' and the literal ``1``. @@ -950,7 +954,7 @@ and the :ref:`imaginary literal ` ``2j``. .. _integers: Integer literals ----------------- +^^^^^^^^^^^^^^^^ Integer literals denote whole numbers. For example:: @@ -1023,26 +1027,58 @@ Formally, integer literals are described by the following lexical definitions: .. _floating: Floating-point literals ------------------------ +^^^^^^^^^^^^^^^^^^^^^^^ -Floating-point literals are described by the following lexical definitions: +Floating-point (float) literals, such as ``3.14`` or ``1.5``, denote +:ref:`approximations of real numbers `. -.. productionlist:: python-grammar - floatnumber: `pointfloat` | `exponentfloat` - pointfloat: [`digitpart`] `fraction` | `digitpart` "." - exponentfloat: (`digitpart` | `pointfloat`) `exponent` - digitpart: `digit` (["_"] `digit`)* - fraction: "." `digitpart` - exponent: ("e" | "E") ["+" | "-"] `digitpart` +They consist of *integer* and *fraction* parts, each composed of decimal digits. +The parts are separated by a decimal point, ``.``:: + + 2.71828 + 4.0 + +Unlike in integer literals, leading zeros are allowed in the numeric parts. +For example, ``077.010`` is legal, and denotes the same number as ``77.10``. + +As in integer literals, single underscores may occur between digits to help +readability:: + + 96_485.332_123 + 3.14_15_93 + +Either of these parts, but not both, can be empty. For example:: -Note that the integer and exponent parts are always interpreted using radix 10. -For example, ``077e010`` is legal, and denotes the same number as ``77e10``. The -allowed range of floating-point literals is implementation-dependent. As in -integer literals, underscores are supported for digit grouping. + 10. # (equivalent to 10.0) + .001 # (equivalent to 0.001) -Some examples of floating-point literals:: +Optionally, the integer and fraction may be followed by an *exponent*: +the letter ``e`` or ``E``, followed by an optional sign, ``+`` or ``-``, +and a number in the same format as the integer and fraction parts. +The ``e`` or ``E`` represents "times ten raised to the power of":: - 3.14 10. .001 1e100 3.14e-10 0e0 3.14_15_93 + 1.0e3 # (represents 1.0×10³, or 1000.0) + 1.166e-5 # (represents 1.166×10⁻⁵, or 0.00001166) + 6.02214076e+23 # (represents 6.02214076×10²³, or 602214076000000000000000.) + +In floats with only integer and exponent parts, the decimal point may be +omitted:: + + 1e3 # (equivalent to 1.e3 and 1.0e3) + 0e0 # (equivalent to 0.) + +Formally, floating-point literals are described by the following +lexical definitions: + +.. grammar-snippet:: + :group: python-grammar + + floatnumber: + | `digitpart` "." [`digitpart`] [`exponent`] + | "." `digitpart` [`exponent`] + | `digitpart` `exponent` + digitpart: `digit` (["_"] `digit`)* + exponent: ("e" | "E") ["+" | "-"] `digitpart` .. versionchanged:: 3.6 Underscores are now allowed for grouping purposes in literals. @@ -1053,7 +1089,7 @@ Some examples of floating-point literals:: .. _imaginary: Imaginary literals ------------------- +^^^^^^^^^^^^^^^^^^ Imaginary literals are described by the following lexical definitions: From e733902a609bde4f069fe8d6dda89ec7ddad3844 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Wed, 28 May 2025 17:38:11 +0200 Subject: [PATCH 6/7] Expand section on imaginary literals --- Doc/reference/lexical_analysis.rst | 60 +++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 14 deletions(-) diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index 54d61949dc1352..ebaeb6130804eb 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -939,11 +939,6 @@ Numeric literals do not include a sign; a phrase like ``-1`` is actually an expression composed of the unary operator '``-``' and the literal ``1``. -Similarly, there are no complex literals; the expression ``1+2j`` is composed -of the :ref:`integer literal ` ``1``, -the :ref:`operator ` '``+``', -and the :ref:`imaginary literal ` ``2j``. - .. index:: single: 0b; integer literal @@ -1091,18 +1086,55 @@ lexical definitions: Imaginary literals ^^^^^^^^^^^^^^^^^^ -Imaginary literals are described by the following lexical definitions: +There are no complex literals. +Instead, :ref:`complex numbers ` can be written +as adding the complex number's real part and imaginary part. -.. productionlist:: python-grammar - imagnumber: (`floatnumber` | `digitpart`) ("j" | "J") +For example, the imaginary number 3.1+4\ *i* can be written as adding the +real number 3.1 to the imaginary number 4\ *i*. +In Python, the imaginary unit is written ``j`` rather than *i* to prevent +confusion with a traditional short name for an index variable:: + + 3.1+4j + +This is an expression composed +of the :ref:`float literal ` ``3.1``, +the :ref:`operator ` '``+``', +and the :ref:`imaginary literal ` ``4j``. +Since these are three separate tokens, whitespace is allowed between them:: + + 3.1 + 4j + +The ``j`` suffix, however, may not be separated from the numeric part +of the imaginary literal. + +The numeric part has the same syntax as a floating-point literal. +Thus, the following are valid imaginary literals:: -An imaginary literal yields a complex number with a real part of 0.0. Complex -numbers are represented as a pair of floating-point numbers and have the same -restrictions on their range. To create a complex number with a nonzero real -part, add a floating-point number to it, e.g., ``(3+4j)``. Some examples of -imaginary literals:: + 3.14j + 10.j + .001j + 1e100j + 3.14e-10j + 3.14_15_93j - 3.14j 10.j 10j .001j 1e100j 3.14e-10j 3.14_15_93j +If the number only has an integer part, the decimal point can be omitted. +The number is still evaluated as a floating-point number, not an integer:: + + 10j + 0j + 1000000000000000000000000j # equivalent to 1e+24j + +The ``j`` suffix is case-insensitive:: + + 3.14J # equivalent to 3.14j + +Formally, imaginary literals are described by the following lexical definition: + +.. grammar-snippet:: + :group: python-grammar + + imagnumber: (`floatnumber` | `digitpart`) ("j" | "J") .. _operators: From ad4f664285501d2be404e55fc755f2f9740f919b Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Wed, 4 Jun 2025 16:12:33 +0200 Subject: [PATCH 7/7] Rewrite the introduction for Imaginary literals --- Doc/reference/lexical_analysis.rst | 37 +++++++++++++++++------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/Doc/reference/lexical_analysis.rst b/Doc/reference/lexical_analysis.rst index ebaeb6130804eb..567c70111c20ec 100644 --- a/Doc/reference/lexical_analysis.rst +++ b/Doc/reference/lexical_analysis.rst @@ -1086,31 +1086,34 @@ lexical definitions: Imaginary literals ^^^^^^^^^^^^^^^^^^ -There are no complex literals. -Instead, :ref:`complex numbers ` can be written -as adding the complex number's real part and imaginary part. +Python has :ref:`complex number ` objects, but no complex +literals. +Instead, *imaginary literals* denote complex numbers with a zero +real part. -For example, the imaginary number 3.1+4\ *i* can be written as adding the -real number 3.1 to the imaginary number 4\ *i*. -In Python, the imaginary unit is written ``j`` rather than *i* to prevent -confusion with a traditional short name for an index variable:: +For example, in math, the complex number 3+4.2\ *i* is written +as the real number 3 added to the imaginary number 4.2\ *i*. +Python uses a similar syntax, except the imaginary unit is written as ``j`` +rather than *i*:: - 3.1+4j + 3+4.2j This is an expression composed -of the :ref:`float literal ` ``3.1``, +of the :ref:`integer literal ` ``3``, the :ref:`operator ` '``+``', -and the :ref:`imaginary literal ` ``4j``. +and the :ref:`imaginary literal ` ``4.2j``. Since these are three separate tokens, whitespace is allowed between them:: - 3.1 + 4j + 3 + 4.2j -The ``j`` suffix, however, may not be separated from the numeric part -of the imaginary literal. +No whitespace is allowed *within* each token. +In particular, the ``j`` suffix, may not be separated from the number +before it. -The numeric part has the same syntax as a floating-point literal. +The number before the ``j`` has the same syntax as a floating-point literal. Thus, the following are valid imaginary literals:: + 4.2j 3.14j 10.j .001j @@ -1118,14 +1121,16 @@ Thus, the following are valid imaginary literals:: 3.14e-10j 3.14_15_93j -If the number only has an integer part, the decimal point can be omitted. +Unlike in a floating-point literal the decimal point can be omitted if the +imaginary number only has an integer part. The number is still evaluated as a floating-point number, not an integer:: 10j 0j 1000000000000000000000000j # equivalent to 1e+24j -The ``j`` suffix is case-insensitive:: +The ``j`` suffix is case-insensitive. +That means you can use ``J`` instead:: 3.14J # equivalent to 3.14j