2017-02-04 3 views
3

Wenn ich Quellcode mit dem ast Modul analysieren, warum ist das lineno Attribut eines Name innerhalb eines FormattedValue auf 1 gesetzt, auch wenn die f-String ist nicht auf Linie 1?Zeilennummern von Python f-Strings in abstrakte Syntaxbaum

Ich versuche zu sehen, welche Zeilen des Quellcodes in einer Funktionsdefinition enthalten sind, also gehe ich die abstrakten Syntaxbaumknoten unter dem FunctionDef Knoten. Ich sammle alle lineno Attribute in eine Menge, und das sagt mir, welche Linien sind Teil der Funktionsdefinition.

Wenn jedoch f-strings in Python 3.6 erschien, haben sie diese Technik irgendwie durchbrochen. Hier ist ein Beispiel für das Problem:

import ast 

code = """\ 

f'x{y}' 
""" 

tree = ast.parse(code) 

print(ast.dump(tree, include_attributes=True)) 

Hier ist die Ausgabe von diesem Skript:

Module(body=[Expr(value=JoinedStr(values=[Str(s='x', lineno=2, col_offset=0), FormattedValue(value=Name(id='y', ctx=Load(), lineno=1, col_offset=1), conversion=-1, format_spec=None, lineno=2, col_offset=0)], lineno=2, col_offset=0), lineno=2, col_offset=0)]) 

Ich weiß, das ist ziemlich unleserlich, so ist hier die gleiche Leistung mit einigen zusätzlichen Leerzeichen:

Module(body=[Expr(value=JoinedStr(values=[ 
    Str(s='x', lineno=2, col_offset=0), 
    FormattedValue(value=Name(id='y', 
           ctx=Load(), 
           lineno=1, 
           col_offset=1), 
        conversion=-1, 
        format_spec=None, 
        lineno=2, 
        col_offset=0)], lineno=2, col_offset=0), lineno=2, col_offset=0)]) 

Der einzige Quellcode war in Zeile 2, also was ist mit diesem Teil der Ausgabe?

Name(id='y', 
    ctx=Load(), 
    lineno=1, 
    col_offset=1) 

Ich dachte, es könnte die Zeilennummer innerhalb die Zeichenfolge sein, aber wenn ich dies versuchen, meldet es noch lineno=1.

code = """\ 

f''' 

x{y}''' 
""" 

Antwort

4

Nach einiger Forschung scheint es, dass f-Saiten sind mächtiger als ich erkannte. Jede geschweifte Klammer ist nicht nur ein Wörterbuchschlüssel wie in früheren Python-Versionen, sondern ein vollständiger Block von Python-Code. Das heißt, Sie Python-Ausdrücke in den Klammern wie folgt schreiben können:

f'x{y + z}' 

Mit diesem Verständnis ist es sinnvoll, dass der lineno Wert ist die Zeilennummer innerhalb der geschweiften Klammern, nicht innerhalb der Zeichenfolge oder innerhalb der gesamten Datei . Um diese Theorie zu testen, habe ich versucht, diesen Code und die lineno geändert 3.

code = """\ 

f'''x{ 

y}''' 
""" 

Wenn ich einfach ignorieren Zeilennummern von FormattedValue Knoten, mein Code funktioniert wieder.

Verwandte Themen