32

So I saw these two questions on twitter. How is 1.real a syntax error but 1 .real is not?

>>> 1.real
  File "<stdin>", line 1
    1.real
         ^
SyntaxError: invalid syntax
>>> 1 .real
1
>>> 1. real
  File "<stdin>", line 1
    1. real
          ^
SyntaxError: invalid syntax
>>> 1 . real
1
>>> 1..real
1.0
>>> 1 ..real
  File "<stdin>", line 1
    1 ..real
       ^
SyntaxError: invalid syntax
>>> 1.. real
1.0
>>> 1 .. real
  File "<stdin>", line 1
    1 .. real
       ^
SyntaxError: invalid syntax
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
AlexLordThorsen
  • 8,057
  • 5
  • 48
  • 103
  • 8
    I guess `1.` is greedily parsed to a float number, and then `real` is missing the `.`, whereas `1 .real` parses `1` as an `int`. Spaces are not allowed around decimal point, but you can have spaces before and after 'method accessor dot' (for lack of a better name). – tobias_k Jun 24 '15 at 21:46
  • This has been asked before, I think repeatedly. I'm having trouble finding the dupes, though. – user2357112 Jun 24 '15 at 21:47
  • 1
    Probably one of these: http://stackoverflow.com/questions/13390458/why-doesnt-2-add-3-work-in-python or http://stackoverflow.com/questions/26255693/attribute-access-on-int-literals – user2357112 Jun 24 '15 at 21:49
  • 2
    try: `(1).real` or `1.0.real` or `1..real` (they are all the same) – fferri Jun 24 '15 at 21:50
  • 4
    There are arguments to change this behavior, but if you make `1.real` an attribute access, then `1.e4` looks like an attribute access, and perfectly fine code that used to produce `10000.0` suddenly produces an AttributeError. It's not worth the hassle. I'm pretty sure Ruby allows this kind of access, since ints have more interesting methods over there; I'm not sure what they do to handle it. – user2357112 Jun 24 '15 at 21:52
  • 1
    Possibly also useful: http://stackoverflow.com/questions/10955703/accessing-a-python-int-literals-methods – Zero Piraeus Jun 24 '15 at 21:56
  • 3
    Aside: Please try to avoid clickbait question titles -- that is to say, please try to add enough information that someone can have a reasonable idea of whether a question is interesting or applicable to them *before* they click to open it. I've attempted to edit this to do so here. – Charles Duffy Jun 24 '15 at 22:07
  • @CharlesDuffy Sorry about that. – AlexLordThorsen Jun 24 '15 at 22:11
  • 1
    @user2357112 From brief experimentation, Ruby allows `1.real` by disallowing `1.` as syntax for a floating point number. So `1.e4` can *only* be a call of the `e4` method on `1`. – Ben Jun 24 '15 at 23:09
  • Note: the same exact thing happens basically in **most** damn languages. I believe I read exactly the same thing about javascript just the other day. That's simply the way in which float and attribute accesses are parsed by *most* languages out there. – Bakuriu Jun 25 '15 at 07:40
  • 1
    Possible duplicate of [What is python .. ("dot dot") notation syntax?](http://stackoverflow.com/questions/43487811/what-is-python-dot-dot-notation-syntax) – TylerH Apr 21 '17 at 14:56

3 Answers3

57

I guess that the . is greedily parsed as part of a number, if possible, making it the float 1., instead of being part of the method call.

Spaces are not allowed around the decimal point, but you can have spaces before and after the . in a method call. If the number is followed by a space, the parse of the number is terminated, so it's unambiguous.

Let's look at the different cases and how they are parsed:

>>> 1.real    # parsed as (1.)real  -> missing '.'
>>> 1 .real   # parsed as (1).real  -> okay
>>> 1. real   # parsed as (1.)real  -> missing '.'
>>> 1 . real  # parsed as (1).real  -> okay
>>> 1..real   # parsed as (1.).real -> okay
>>> 1 ..real  # parsed as (1)..real -> one '.' too much
>>> 1.. real  # parsed as (1.).real -> okay
>>> 1 .. real # parsed as (1)..real -> one '.' too much
tobias_k
  • 81,265
  • 12
  • 120
  • 179
  • 7
    I was tempted to downvote this simply because I don't want to admit that `1..real` is "okay"....+1 though for showing me something (cringe-worthy) that I didn't realize. – That1Guy Jun 24 '15 at 22:12
  • 12
    Fun fact: SO's syntax highlighting for this answer is consistent with how Python interprets it. That is, there should be exactly one black dot (as opposed to the reddish dot) between the `1` and the `real`. – leewz Jun 25 '15 at 04:38
  • @leewangzhong Well, SO uses google-prettify to perform highlighting and it's well-known that google uses a lot of Python so it's not surprising that the highlighting is actually a good one and not just a naive approximation... – Bakuriu Jun 25 '15 at 08:42
11

With 1.real Python is looking for a floating-point numeric literal like 1.0 and you can't have an r in a float. With 1 .real Python has taken 1 as an integer and is doing the attribute lookup on that.

It's important to note that the floating-point syntax error handling happens before the . attribute lookup.

AlexLordThorsen
  • 8,057
  • 5
  • 48
  • 103
kindall
  • 178,883
  • 35
  • 278
  • 309
  • why does `1.real` cause a syntax error if there's a member called `real`? – AlexLordThorsen Jun 24 '15 at 21:50
  • `[0-9].[0-9]` is how a float is defined it partially matches and fails you cannot do direct attribute lookups on integers without letting the interpretter somehow know that its an attribute and not a float – Joran Beasley Jun 24 '15 at 21:50
  • 1
    type `dir(int())` you will see many methods ... you cannot access any of them as `1.xxxx` however you can access any of them with `1 .xxxx` or `(1).xxxxx` – Joran Beasley Jun 24 '15 at 21:51
  • 1
    Ahh, because the `.` in the floating point takes precedent over the `.` in attribute lookup. – AlexLordThorsen Jun 24 '15 at 21:51
  • yes effectively at least since evaluating the type is a very high precedence operation ... (really I dont think precedence is the way to describe it, however before you can look up attributes, the interpreter must know what its looking up attributes on) – Joran Beasley Jun 24 '15 at 21:52
  • 1
    @JoranBeasley Ohhh. So `1.real` is like writing `1. real` which is invalid. – Malik Brahimi Jun 24 '15 at 22:13
  • @JoranBeasley is that `[0-9]+.[0-9]+|.[0-9]+|[0-9]+.`? – PythonNut Jun 25 '15 at 00:53
  • 1
    @kindall The point is that most people resolve syntax ambiguities with parentheses. Not with whitespace. – Navin Jun 25 '15 at 01:44
1

1 .real works because it is the attribute .real called on the integer 1.

1.real does not work, because you imperatively need a space at the end of a float. Otherwise it is a syntax error.

DevShark
  • 8,558
  • 9
  • 32
  • 56