Der Zugriff auf Attribute von Literalen funktioniert auf allen Arten, jedoch nicht auf "int". Warum?

  • Ich habe gelesen, dass alles in Python ein Objekt ist, und so fing ich an, mit verschiedenen Typen zu experimentieren und __str__ darauf aufzurufen - zunächst fühlte ich mich Wirklich aufgeregt, aber dann wurde ich verwirrt.

    >>> "hello world".__str__() 'hello world' >>> [].__str__() '[]' >>> 3.14.__str__() '3.14' >>> 3..__str__() '3.0' >>> 123.__str__() File "<stdin>", line 1 123.__str__() ^ SyntaxError: invalid syntax
    • Warum? e> für "alles" neben s int arbeiten?
    • Ich s 123 kein Objekt vom Typ e int? li>
    14 October 2015
    Martijn Pieters
4 answers
  • Sie benötigen Eltern:

     (4).__str__()
     

    Das Problem ist, dass der Lexer "4" denkt. wird eine Gleitkommazahl sein.

    Das funktioniert auch:

     x = 4
    x.__str__()
     
    10 October 2015
    Filip Roséen - refp
  • Sie glauben also, Sie können tanzen Fließkommazahl?

    123 ist ebenso ein Objekt eines s 3.14 float zu definieren - nicht einen int mit einem nachlaufenden Methodenaufruf.

    Wir werden bekommen das erwartete Verhalten, wenn wir die Zahl in Klammern einschließen, wie in der folgenden Tabelle.

    >>> (123).__str__()
    '123' 

    Oder wenn wir einfach hinzufügen etwas Leerzeichen nach 123 :

    >>> 123 .__str__()
    '123' 


    Der Grund, warum es nicht funktioniert for 123.__str__() ist, dass der Punkt nach dem 123 als Dezimalzahl interpretiert wird -Punkt eines teilweise deklarierten Fließpunkts .

    >>> 123.__str__()
      File "", line 1
        123.__str__()
                  ^
    SyntaxError: invalid syntax 

    Der Parser versucht, ret __str__() als Folge von Ziffern einzugeben, schlägt jedoch fehl - und wir erhalten einen SyntaxError , der besagt, dass der Parser auf etwas gestoßen ist, das er nicht erwartet hat.



    Ausarbeitung

    Bei looki ng at 123.__str__()< / code> könnte der Python-Parser entweder 3 -Zeichen verwenden und diese 3 -Zeichen als -Integer interpretieren , oder Es könnten 4 Zeichen verwendet werden und diese als Start eines Fließkommas interpretiert werden .

    123.__str__()
    ^^^ - int
    < / code> 
    123.__str__()
    ^^^^- start of floating-point
    < / code> 

    So wie ein kleines Kind möglichst viel Kuchen auf dem Teller haben möchte, ist der Parser gierig und möchte so viel wie möglich auf einmal schlucken - auch wenn dies nicht immer die beste Idee ist - als solche ("bessere") Alternative wird gewählt.

    Wenn es später real ist, kann izes that __str_ _ () keinesfalls als Dezimalzahlen eines Fließkommas ist schon zu spät; SyntaxError .

    Hinweis

      123 .__ str __ () # funktioniert gut 
      

    InDas obige Snippet 123 (beachten Sie das Leerzeichen) muss als Ganzzahl interpretiert werden, da keine -Zahl Leerzeichen enthalten kann. Dies bedeutet, dass es semantisch äquivalent ist zu (123) .__ str__ () .

    Hinweis

      123 ..__ str __ () # funktioniert gut 
      

    Dies funktioniert auch, weil eine -Zahl höchstens einen Dezimalpunkt enthalten kann, was bedeutet, dass sie gleichwertig ist zu (123.) .__ str __ () .



    Für die Sprachanwälte

    Dieser Abschnitt enthält die lexikalische Definition der relevanten Literale.

    Lexikalisch Analyse - 2.4.5 Fließkomma-Literale

      floatnumber :: = pointfloat | exponentfloat 
     pointfloat :: = [intpart] Bruchteil | intpart "." 
     exponentfloat :: = (intpart | pointfloat) Exponent 
     intpart :: = digit + 
     Fraktion :: = "." digit + 
     exponent :: = ("e" | "E") ["+" | "-"] digit + 
      

    Lexikalische Analyse - 2.4.4 Integer-Literale

      Integer: : = decimalinteger | Oktinteger | hexinteger | bininteger 
     dezimalinteger :: = nichtzifferzahlige Ziffer * | "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" | & #
                                        
    14 October 2015
    Anand S KumarRyan
  • Fügen Sie nach 4 ein Leerzeichen ein:

     4 .__str__()
     

    Andernfalls wird der Lexer aufgeteilt diesen Ausdruck in die Token "4.", "__str__", "(" und ")", dh das erste Token wird als Fließkommazahl interpretiert. Der Lexer versucht immer, ein möglichst langes Token zu erstellen.

    10 October 2015
    Filip Roséen - refp
  • eigentlich (um die Lesbarkeit zu erhöhen ...):

     4..hex()
     

    ist ebenfalls gültig. es gibt '0x1.0000000000000p+2' - aber dann ist es natürlich ein Float ...

    09 June 2012
    kratenkomanish Sawant