Decimal (i.e. non-prefixed) integers in Python seem to have fewer features than prefixed integers.
If I do 1.real
I get a SyntaxError: invalid decimal literal
. However, if I do 0x1.real
, then I get no error and 1
is the result. (Same for 0b1.real
and 0o1.real
, though in Python2 01.real
gives a syntax error as).
It's because the 1.
lead-in is being treated as a floating-point literal and r
is not a valid decimal digit.
Hex literals, of the form you show, are integers, so are not ambiguous in being treated as a possible floating point (there is no 0x1.1
).
If you use (1).real
to specify that the literal is just the 1
, it works fine.
The following (annotated) transcript may help:
>>> 0x1.real # Can only be integer, so works as expected.
1
>>> 1.real # Treated as floating point, "r" is invalid,
File "<stdin>", line 1
1.real
^
SyntaxError: invalid syntax
>>> (1).real # Explicitly remove ambiguity, works.
1
>>> 0x1.1 # No float hex literal in this form.
File "<stdin>", line 1
0x1.1
^
SyntaxError: invalid syntax
For completeness, the lexical tokens for numerics (integral and float) can be found in the Python docs:
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"
floatnumber ::= pointfloat | exponentfloat
pointfloat ::= [digitpart] fraction | digitpart "."
exponentfloat ::= (digitpart | pointfloat) exponent
digitpart ::= digit (["_"] digit)*
fraction ::= "." digitpart
exponent ::= ("e" | "E") ["+" | "-"] digitpart
You can see there that the floats do not allow for hexadecimal prefixes, which is why it can safely assume the .
in 0x1.real
is not part of the literal value.
That's not the case for 1.real
, it assumes that the .
is preceding a fractional part of a float.
A clever-enough lexer could, of course, detect an invalid decimal digit immediately after the .
and therefore assume it's a method to call on an integer. But that introduces complexity and may have other problematic edge cases.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With