python python-3.x integer literals leading-zero

¿Por qué Python 3 permite "00" como literal para 0 pero no permite "01" como literal para 1?



python-3.x integer (3)

Es un caso especial ( "0"+ )

https://docs.python.org/3/reference/lexical_analysis.html#integer-literals https://docs.python.org/3/reference/lexical_analysis.html#integer-literals

Integer literals are described by the following lexical definitions: integer ::= decimalinteger | octinteger | hexinteger | bininteger decimalinteger ::= nonzerodigit digit* | "0"+ nonzerodigit ::= "1"..."9" digit ::= "0"..."9" octinteger ::= "0" ("o" | "O") octdigit+ hexinteger ::= "0" ("x" | "X") hexdigit+ bininteger ::= "0" ("b" | "B") bindigit+ octdigit ::= "0"..."7" hexdigit ::= digit | "a"..."f" | "A"..."F" bindigit ::= "0" | "1"

Si observa la gramática, es fácil ver que 0 necesita un caso especial. Sin embargo, no estoy seguro de por qué el '' + '' se considera necesario allí. Es hora de explorar la lista de correo del desarrollador ...

Es interesante notar que en Python2, más de un 0 se analizó como un octinteger ( octinteger el resultado final sigue siendo 0 )

decimalinteger ::= nonzerodigit digit* | "0" octinteger ::= "0" ("o" | "O") octdigit+ | "0" octdigit+

¿Por qué Python 3 permite "00" como literal para 0 pero no permite "01" como literal para 1? ¿Hay una buena razón? Esta inconsistencia me desconcierta. (Y estamos hablando de Python 3, que deliberadamente rompió la compatibilidad con versiones anteriores para lograr objetivos como la coherencia).

Por ejemplo:

>>> from datetime import time >>> time(16, 00) datetime.time(16, 0) >>> time(16, 01) File "<stdin>", line 1 time(16, 01) ^ SyntaxError: invalid token >>>


Por https://docs.python.org/3/reference/lexical_analysis.html#integer-literals :

Los literales enteros se describen mediante las siguientes definiciones léxicas:

integer ::= decimalinteger | octinteger | hexinteger | bininteger decimalinteger ::= nonzerodigit digit* | "0"+ nonzerodigit ::= "1"..."9" digit ::= "0"..."9" octinteger ::= "0" ("o" | "O") octdigit+ hexinteger ::= "0" ("x" | "X") hexdigit+ bininteger ::= "0" ("b" | "B") bindigit+ octdigit ::= "0"..."7" hexdigit ::= digit | "a"..."f" | "A"..."F" bindigit ::= "0" | "1"

No hay límite para la longitud de los literales enteros, aparte de lo que se puede almacenar en la memoria disponible.

Tenga en cuenta que los ceros iniciales en un número decimal distinto de cero no están permitidos. Esto es para la desambiguación con literales octales de estilo C, que Python utilizó antes de la versión 3.0.

Como se señaló aquí, no se permiten ceros a la izquierda en un número decimal distinto de cero . "0"+ es legal como un caso muy especial, que no estaba presente en Python 2 :

integer ::= decimalinteger | octinteger | hexinteger | bininteger decimalinteger ::= nonzerodigit digit* | "0" octinteger ::= "0" ("o" | "O") octdigit+ | "0" octdigit+

SVN commit r55866 implementó PEP 3127 en el tokenizer, que prohíbe los viejos números 0<octal> . Sin embargo, curiosamente, también agrega esta nota:

/* in any case, allow ''0'' as a literal */

con un indicador especial nonzero que solo arroja un SyntaxError si la siguiente secuencia de dígitos contiene un dígito distinto de cero.

Esto es extraño porque PEP 3127 no permite este caso:

Este PEP propone que la capacidad de especificar un número octal mediante el uso de un cero inicial se eliminará del lenguaje en Python 3.0 (y el modo de vista previa Python 3.0 de 2.6), y que se generará un SyntaxError siempre que aparezca un "0" inicial seguido inmediatamente por otro dígito .

(énfasis mío)

Entonces, el hecho de que se permitan múltiples ceros está violando técnicamente la PEP, y básicamente fue implementado como un caso especial por Georg Brandl. Hizo el cambio de documentación correspondiente para notar que "0"+ era un caso válido para decimalinteger (anteriormente había sido cubierto bajo octinteger ).

Probablemente nunca sabremos exactamente por qué Georg eligió hacer que "0"+ válido; para siempre puede ser un caso extraño en Python.

ACTUALIZACIÓN [28 de julio de 2015]: esta pregunta condujo a un hilo de discusión animado sobre ideas de python en el que Georg intervino :

Steven D''Aprano escribió:

¿Por qué se definió de esa manera? [...] ¿Por qué escribiríamos 0000 para obtener cero?

Podría decírtelo, pero luego tendría que matarte.

Georg

Más tarde, el hilo generó este informe de error con el objetivo de deshacerse de este caso especial. Aquí, Georg dice :

No recuerdo la razón de este cambio deliberado (como se ve en el cambio de documentos).

No puedo encontrar una buena razón para este cambio ahora [...]

y así lo tenemos: la razón precisa detrás de esta inconsistencia se pierde en el tiempo.

Finalmente, tenga en cuenta que el informe de error fue rechazado: los ceros iniciales seguirán siendo aceptados solo en enteros cero para el resto de Python 3.x.


Python2 usó el cero inicial para especificar números octales:

>>> 010 8

Para evitar este comportamiento (¿engañoso?), Python3 requiere prefijos explícitos 0b , 0o , 0x :

>>> 0o10 8