YAPF ist ein Python-Formatierer, der auf clang-format
(entwickelt von Daniel Jasper) basiert. Im Wesentlichen nimmt der Algorithmus den Code und berechnet die beste Formatierung, die dem konfigurierten Stil entspricht. Es nimmt Ihnen einen Großteil der Plackerei bei der Pflege Ihres Codes ab.
Das ultimative Ziel besteht darin, dass der von YAPF erzeugte Code so gut ist wie der Code, den ein Programmierer schreiben würde, wenn er den Styleguide befolgen würde.
Hinweis: YAPF ist kein offizielles Google-Produkt (experimentell oder anderweitig), es handelt sich lediglich um Code, der zufällig Eigentum von Google ist.
So installieren Sie YAPF von PyPI:
$ pip install yapf
YAPF befindet sich noch im „Beta“-Stadium und die veröffentlichte Version kann sich häufig ändern; Daher ist der beste Weg, über die neueste Entwicklung auf dem Laufenden zu bleiben, dieses Repository zu klonen oder direkt von Github aus zu installieren:
$ pip install git+https://github.com/google/yapf.git
Beachten Sie, dass eine Installation nicht erforderlich ist, wenn Sie YAPF als Befehlszeilentool und nicht als Bibliothek verwenden möchten. YAPF unterstützt die Ausführung als Verzeichnis durch den Python-Interpreter. Wenn Sie YAPF in DIR
geklont/entpackt haben, ist es möglich, Folgendes auszuführen:
$ PYTHONPATH=DIR python DIR/yapf [options] ...
YAPF wird von mehreren Editoren über Community-Erweiterungen oder Plugins unterstützt. Weitere Informationen finden Sie unter Editor-Unterstützung.
YAPF unterstützt Python 3.7+.
usage: yapf [-h] [-v] [-d | -i | -q] [-r | -l START-END] [-e PATTERN]
[--style STYLE] [--style-help] [--no-local-style] [-p] [-m] [-vv]
[files ...]
Formatter for Python code.
positional arguments:
files reads from stdin when no files are specified.
optional arguments:
-h, --help show this help message and exit
-v, --version show program's version number and exit
-d, --diff print the diff for the fixed source
-i, --in-place make changes to files in place
-q, --quiet output nothing and set return value
-r, --recursive run recursively over directories
-l START-END, --lines START-END
range of lines to reformat, one-based
-e PATTERN, --exclude PATTERN
patterns for files to exclude from formatting
--style STYLE specify formatting style: either a style name (for
example "pep8" or "google"), or the name of a file
with style settings. The default is pep8 unless a
.style.yapf or setup.cfg or pyproject.toml file
located in the same directory as the source or one of
its parent directories (for stdin, the current
directory is used).
--style-help show style settings and exit; this output can be saved
to .style.yapf to make your settings permanent
--no-local-style don't search for local style definition
-p, --parallel run YAPF in parallel when formatting multiple files.
-m, --print-modified print out file names of modified files
-vv, --verbose print out file names while processing
Normalerweise gibt YAPF bei erfolgreicher Programmbeendigung Null zurück und andernfalls einen Wert ungleich Null.
Wenn --diff
angegeben wird, gibt YAPF Null zurück, wenn keine Änderungen erforderlich waren, ansonsten einen Wert ungleich Null (einschließlich Programmfehler). Sie können dies in einem CI-Workflow verwenden, um zu testen, ob der Code YAPF-formatiert wurde.
Zusätzlich zu den auf der Befehlszeile bereitgestellten Ausschlussmustern sucht YAPF nach zusätzlichen Mustern, die in einer Datei namens .yapfignore
oder pyproject.toml
angegeben sind, die sich im Arbeitsverzeichnis befindet, aus dem YAPF aufgerufen wird.
Die Syntax von .yapfignore
ähnelt dem Dateinamenmustervergleich von UNIX:
* matches everything
? matches any single character
[seq] matches any character in seq
[!seq] matches any character not in seq
Beachten Sie, dass kein Eintrag mit ./
beginnen sollte.
Wenn Sie pyproject.toml
verwenden, werden Ausschlussmuster durch den Schlüssel ignore_patterns
im Abschnitt [tool.yapfignore]
angegeben. Zum Beispiel:
[tool.yapfignore]
ignore_patterns = [
" temp/**/*.py " ,
" temp2/*.py "
]
Der von YAPF verwendete Formatierungsstil ist konfigurierbar und es gibt viele „Regler“, mit denen Sie die Formatierung durch YAPF optimieren können. Die vollständige Liste finden Sie im Modul style.py
.
Um den Stil zu steuern, führen Sie YAPF mit dem Argument --style
aus. Es akzeptiert einen der vordefinierten Stile (z. B. pep8
oder google
), einen Pfad zu einer Konfigurationsdatei, die den gewünschten Stil angibt, oder ein Wörterbuch mit Schlüssel/Wert-Paaren.
Die Konfigurationsdatei ist eine einfache Auflistung von key = value
Paaren (ohne Berücksichtigung der Groß- und Kleinschreibung) mit einer [style]
-Überschrift. Zum Beispiel:
[style]
based_on_style = pep8
spaces_before_comment = 4
split_before_logical_operator = true
Die Einstellung based_on_style
bestimmt, auf welchem der vordefinierten Stile dieser benutzerdefinierte Stil basiert (stellen Sie sich das wie eine Unterklasse vor). Vier Stile sind vordefiniert:
pep8
(Standard)google
(basierend auf dem Google Python Style Guide)yapf
(zur Verwendung mit Google-Open-Source-Projekten)facebook
Weitere Informationen finden Sie unter _STYLE_NAME_TO_FACTORY
in style.py
.
Das Gleiche ist auch über die Befehlszeile mit einem Wörterbuch möglich. Zum Beispiel:
--style= ' {based_on_style: pep8, indent_width: 2} '
Dadurch wird der pep8
Basisstil übernommen und so geändert, dass er zwei Leerzeicheneinzüge aufweist.
YAPF sucht auf folgende Weise nach dem Formatierungsstil:
[style]
einer .style.yapf
Datei im aktuellen Verzeichnis oder einem seiner übergeordneten Verzeichnisse.[yapf]
einer setup.cfg
Datei im aktuellen Verzeichnis oder einem seiner übergeordneten Verzeichnisse.[tool.yapf]
einer pyproject.toml
Datei entweder im aktuellen Verzeichnis oder in einem seiner übergeordneten Verzeichnisse.[style]
einer Datei ~/.config/yapf/style
in Ihrem Home-Verzeichnis.Wenn keine dieser Dateien gefunden wird, wird der Standardstil PEP8 verwendet.
Ein Beispiel für die Art der Formatierung, die YAPF durchführen kann, ist dieser hässliche Code:
x = { 'a' : 37 , 'b' : 42 ,
'c' : 927 }
y = 'hello ' 'world'
z = 'hello ' + 'world'
a = 'hello {}' . format ( 'world' )
class foo ( object ):
def f ( self ):
return 37 * - + 2
def g ( self , x , y = 42 ):
return y
def f ( a ) :
return 37 + - + a [ 42 - x : y ** 3 ]
und formatieren Sie es neu in:
x = { 'a' : 37 , 'b' : 42 , 'c' : 927 }
y = 'hello ' 'world'
z = 'hello ' + 'world'
a = 'hello {}' . format ( 'world' )
class foo ( object ):
def f ( self ):
return 37 * - + 2
def g ( self , x , y = 42 ):
return y
def f ( a ):
return 37 + - + a [ 42 - x : y ** 3 ]
Die beiden Haupt-APIs zum Aufrufen von YAPF sind FormatCode
und FormatFile
. Diese teilen mehrere Argumente, die im Folgenden beschrieben werden:
> >> from yapf . yapflib . yapf_api import FormatCode # reformat a string of code
> >> formatted_code , changed = FormatCode ( "f ( a = 1, b = 2 )" )
> >> formatted_code
'f(a=1, b=2) n '
> >> changed
True
Ein style_config
Argument: Entweder ein Stilname oder ein Pfad zu einer Datei, die Formatierungsstileinstellungen enthält. Wenn None angegeben ist, verwenden Sie den Standardstil, der in style.DEFAULT_STYLE_FACTORY
festgelegt ist.
> >> FormatCode ( "def g(): n return True" , style_config = 'pep8' )[ 0 ]
'def g(): n return True n '
Ein lines
: Eine Liste von Zeilentupeln (ints), [Start, Ende], die wir formatieren möchten. Die Zeilen sind 1-basiert indiziert. Es kann von Drittanbietercode (z. B. IDEs) verwendet werden, wenn ein Codeausschnitt anstelle einer ganzen Datei neu formatiert wird.
> >> FormatCode ( "def g( ): n a=1 n b = 2 n return a==b" , lines = [( 1 , 1 ), ( 2 , 3 )])[ 0 ]
'def g(): n a = 1 n b = 2 n return a==b n '
Ein print_diff
(bool): Anstatt die neu formatierte Quelle zurückzugeben, geben Sie einen Diff zurück, der die formatierte Quelle in eine neu formatierte Quelle umwandelt.
>>> print(FormatCode("a==b", filename="foo.py", print_diff=True)[0])
--- foo.py (original)
+++ foo.py (reformatted)
@@ -1 +1 @@
- a==b
+ a == b
Hinweis: Das filename
für FormatCode
wird in das Diff eingefügt. Der Standardwert ist <unknown>
.
FormatFile
gibt neu formatierten Code aus der übergebenen Datei zusammen mit seiner Codierung zurück:
> >> from yapf . yapflib . yapf_api import FormatFile # reformat a file
> >> print ( open ( "foo.py" ). read ()) # contents of file
a == b
> >> reformatted_code , encoding , changed = FormatFile ( "foo.py" )
> >> formatted_code
'a == b n '
> >> encoding
'utf-8'
> >> changed
True
Das Argument in_place
speichert den neu formatierten Code zurück in der Datei:
> >> FormatFile ( "foo.py" , in_place = True )[: 2 ]
( None , 'utf-8' )
> >> print ( open ( "foo.py" ). read ()) # contents of file (now fixed)
a == b
Optionen:
usage: yapf-diff [-h] [-i] [-p NUM] [--regex PATTERN] [--iregex PATTERN][-v]
[--style STYLE] [--binary BINARY]
This script reads input from a unified diff and reformats all the changed
lines. This is useful to reformat all the lines touched by a specific patch.
Example usage for git/svn users:
git diff -U0 --no-color --relative HEAD^ | yapf-diff -i
svn diff --diff-cmd=diff -x-U0 | yapf-diff -p0 -i
It should be noted that the filename contained in the diff is used
unmodified to determine the source file to update. Users calling this script
directly should be careful to ensure that the path in the diff is correct
relative to the current working directory.
optional arguments:
-h, --help show this help message and exit
-i, --in-place apply edits to files instead of displaying a diff
-p NUM, --prefix NUM strip the smallest prefix containing P slashes
--regex PATTERN custom pattern selecting file paths to reformat
(case sensitive, overrides -iregex)
--iregex PATTERN custom pattern selecting file paths to reformat
(case insensitive, overridden by -regex)
-v, --verbose be more verbose, ineffective without -i
--style STYLE specify formatting style: either a style name (for
example "pep8" or "google"), or the name of a file
with style settings. The default is pep8 unless a
.style.yapf or setup.cfg or pyproject.toml file
located in the same directory as the source or one of
its parent directories (for stdin, the current
directory is used).
--binary BINARY location of binary to use for YAPF
ALIGN_CLOSING_BRACKET_WITH_VISUAL_INDENT
Richten Sie die schließende Klammer an der visuellen Einkerbung aus.
ALLOW_MULTILINE_LAMBDAS
Ermöglichen Sie die Formatierung von Lambdas in mehr als einer Zeile.
ALLOW_MULTILINE_DICTIONARY_KEYS
Erlauben Sie, dass Wörterbuchschlüssel in mehreren Zeilen vorhanden sind. Zum Beispiel:
x = {
( 'this is the first element of a tuple' ,
'this is the second element of a tuple' ):
value ,
}
ALLOW_SPLIT_BEFORE_DEFAULT_OR_NAMED_ASSIGNS
Erlauben Sie die Aufteilung vor einer Standard-/benannten Zuweisung in einer Argumentliste.
ALLOW_SPLIT_BEFORE_DICT_VALUE
Teilungen vor dem Wörterbuchwert zulassen.
ARITHMETIC_PRECEDENCE_INDICATION
Lassen Sie den Abstand den Vorrang des Operators angeben. Zum Beispiel:
a = 1 * 2 + 3 / 4
b = 1 / 2 - 3 * 4
c = ( 1 + 2 ) * ( 3 - 4 )
d = ( 1 - 2 ) / ( 3 + 4 )
e = 1 * 2 - 3
f = 1 + 2 + 3 + 4
wird wie folgt formatiert, um den Vorrang anzuzeigen:
a = 1 * 2 + 3 / 4
b = 1 / 2 - 3 * 4
c = ( 1 + 2 ) * ( 3 - 4 )
d = ( 1 - 2 ) / ( 3 + 4 )
e = 1 * 2 - 3
f = 1 + 2 + 3 + 4
BLANK_LINES_AROUND_TOP_LEVEL_DEFINITION
Legt die Anzahl der gewünschten Leerzeilen fest, die Funktions- und Klassendefinitionen der obersten Ebene umgeben. Zum Beispiel:
class Foo :
pass
# <------ having two blank lines here
# <------ is the default setting
class Bar :
pass
BLANK_LINE_BEFORE_CLASS_DOCSTRING
Fügen Sie vor einer Dokumentzeichenfolge auf Klassenebene eine Leerzeile ein.
BLANK_LINE_BEFORE_MODULE_DOCSTRING
Fügen Sie vor einer Moduldokumentzeichenfolge eine Leerzeile ein.
BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF
Fügen Sie eine Leerzeile vor einer
def
oderclass
ein, die unmittelbar in einer anderendef
oderclass
verschachtelt ist. Zum Beispiel:
class Foo :
# <------ this blank line
def method ():
pass
BLANK_LINES_BETWEEN_TOP_LEVEL_IMPORTS_AND_VARIABLES
Legt die Anzahl der gewünschten Leerzeilen zwischen Importen der obersten Ebene und Variablendefinitionen fest. Nützlich für die Kompatibilität mit Tools wie isort.
COALESCE_BRACKETS
Teilen Sie aufeinanderfolgende Klammern nicht auf. Nur relevant, wenn
DEDENT_CLOSING_BRACKETS
oderINDENT_CLOSING_BRACKETS
gesetzt ist. Zum Beispiel:
call_func_that_takes_a_dict (
{
'key1' : 'value1' ,
'key2' : 'value2' ,
}
)
würde neu formatieren zu:
call_func_that_takes_a_dict ({
'key1' : 'value1' ,
'key2' : 'value2' ,
})
COLUMN_LIMIT
Das Spaltenlimit (oder die maximale Zeilenlänge)
CONTINUATION_ALIGN_STYLE
Der Stil für die Fortsetzungsausrichtung. Mögliche Werte sind:
SPACE
: Verwenden Sie Leerzeichen für die Fortsetzungsausrichtung. Dies ist das Standardverhalten.FIXED
: Verwenden Sie eine feste Anzahl (CONTINUATION_INDENT_WIDTH
) von Spalten (z. B.CONTINUATION_INDENT_WIDTH
/INDENT_WIDTH
Tabulatoren oderCONTINUATION_INDENT_WIDTH
Leerzeichen) für die Fortsetzungsausrichtung.VALIGN-RIGHT
: Fortsetzungszeilen vertikal an mehrerenINDENT_WIDTH
Spalten ausrichten. Etwas rechts (ein Tabulator oder ein paar Leerzeichen), wenn Fortsetzungszeilen nicht vertikal an Einzugszeichen ausgerichtet werden können.
CONTINUATION_INDENT_WIDTH
Einzugsbreite für Zeilenfortsetzungen.
DEDENT_CLOSING_BRACKETS
Setzen Sie schließende Klammern in eine separate Zeile mit Einzug, wenn der Ausdruck in Klammern nicht in eine einzelne Zeile passt. Gilt für alle Arten von Klammern, einschließlich Funktionsdefinitionen und Aufrufe. Zum Beispiel:
config = {
'key1' : 'value1' ,
'key2' : 'value2' ,
} # <--- this bracket is dedented and on a separate line
time_series = self . remote_client . query_entity_counters (
entity = 'dev3246.region1' ,
key = 'dns.query_latency_tcp' ,
transform = Transformation . AVERAGE ( window = timedelta ( seconds = 60 )),
start_ts = now () - timedelta ( days = 3 ),
end_ts = now (),
) # <--- this bracket is dedented and on a separate line
DISABLE_ENDING_COMMA_HEURISTIC
Deaktivieren Sie die Heuristik, die jedes Listenelement in einer separaten Zeile platziert, wenn die Liste durch Kommas abgeschlossen ist.
Hinweis: Das Verhalten dieses Flags hat sich in Version 0.40.3 geändert. Wenn dieses Flag früher wahr war, haben wir Listen geteilt, die ein abschließendes Komma oder einen Kommentar enthielten. Jetzt haben wir ein separates Flag,
DISABLE_SPLIT_LIST_WITH_COMMENT
, das die Aufteilung steuert, wenn eine Liste einen Kommentar enthält. Um das alte Verhalten zu erhalten, setzen Sie beide Flags auf „true“. Weitere Informationen unter CHANGELOG.md.
DISABLE_SPLIT_LIST_WITH_COMMENT
Platzieren Sie nicht jedes Element in einer neuen Zeile innerhalb einer Liste, die Zwischenkommentare enthält.
Ohne dieses Flag (Standard):
[ a, b, # c ]
Mit dieser Flagge:
[ a, b, # c ]
Dies spiegelt das Verhalten des Clang-Formats wider und ist nützlich für die Bildung „logischer Gruppen“ von Elementen in einer Liste. Es funktioniert auch in Funktionsdeklarationen.
EACH_DICT_ENTRY_ON_SEPARATE_LINE
Platzieren Sie jeden Wörterbucheintrag in einer eigenen Zeile.
FORCE_MULTILINE_DICT
Beachten Sie
EACH_DICT_ENTRY_ON_SEPARATE_LINE
auch wenn die Zeile kürzer alsCOLUMN_LIMIT
ist.
I18N_COMMENT
Der reguläre Ausdruck für einen Internationalisierungskommentar. Das Vorhandensein dieses Kommentars stoppt die Neuformatierung dieser Zeile, da die Kommentare neben der zu übersetzenden Zeichenfolge stehen müssen.
I18N_FUNCTION_CALL
Die Namen der Internationalisierungsfunktionsaufrufe. Das Vorhandensein dieser Funktion stoppt die Neuformatierung in dieser Zeile, da die darin enthaltene Zeichenfolge nicht aus dem i18n-Kommentar entfernt werden kann.
INDENT_BLANK_LINES
Legen Sie den Wert auf
True
fest, um eingerückte Leerzeilen den Vorzug vor leeren Zeilen zu geben
INDENT_CLOSING_BRACKETS
Setzen Sie schließende Klammern in eine separate Zeile mit Einzug, wenn der Ausdruck in Klammern nicht in eine einzelne Zeile passt. Gilt für alle Arten von Klammern, einschließlich Funktionsdefinitionen und Aufrufe. Zum Beispiel:
config = {
'key1' : 'value1' ,
'key2' : 'value2' ,
} # <--- this bracket is indented and on a separate line
time_series = self . remote_client . query_entity_counters (
entity = 'dev3246.region1' ,
key = 'dns.query_latency_tcp' ,
transform = Transformation . AVERAGE ( window = timedelta ( seconds = 60 )),
start_ts = now () - timedelta ( days = 3 ),
end_ts = now (),
) # <--- this bracket is indented and on a separate line
INDENT_DICTIONARY_VALUE
Den Wörterbuchwert einrücken, wenn er nicht in dieselbe Zeile wie der Wörterbuchschlüssel passt. Zum Beispiel:
config = {
'key1' :
'value1' ,
'key2' : value1 +
value2 ,
}
INDENT_WIDTH
Die Anzahl der Spalten, die für die Einrückung verwendet werden sollen.
JOIN_MULTIPLE_LINES
Kurze Zeilen zu einer Zeile zusammenfügen. ZB einzeilige
if
-Anweisungen.
NO_SPACES_AROUND_SELECTED_BINARY_OPERATORS
Fügen Sie keine Leerzeichen um ausgewählte binäre Operatoren ein. Zum Beispiel:
1 + 2 * 3 - 4 / 5
wird bei der Konfiguration mit
*
,/
wie folgt formatiert:
1 + 2 * 3 - 4 / 5
SPACE_BETWEEN_ENDING_COMMA_AND_CLOSING_BRACKET
Fügen Sie zwischen dem Endkomma und der schließenden Klammer einer Liste usw. ein Leerzeichen ein.
SPACE_INSIDE_BRACKETS
Use spaces inside brackets, braces, and parentheses. For example:
method_call ( 1 )
my_dict [ 3 ][ 1 ][ get_index ( * args , ** kwargs ) ]
my_set = { 1 , 2 , 3 }
SPACES_AROUND_DEFAULT_OR_NAMED_ASSIGN
Auf
True
setzen, um Leerzeichen um den Zuweisungsoperator für Standard- oder Schlüsselwortargumente zu bevorzugen.
SPACES_AROUND_DICT_DELIMITERS
Fügt ein Leerzeichen nach dem öffnenden „{“ und vor dem endenden „}“ als Diktattrennzeichen ein.
{ 1 : 2 }
wird wie folgt formatiert:
{ 1 : 2 }
SPACES_AROUND_LIST_DELIMITERS
Fügt nach dem öffnenden „[“ und vor dem endenden „]“-Listentrennzeichen ein Leerzeichen ein.
[ 1 , 2 ]
wird wie folgt formatiert:
[ 1 , 2 ]
SPACES_AROUND_POWER_OPERATOR
Legen Sie
True
fest, um die Verwendung von Leerzeichen um**
zu bevorzugen.
SPACES_AROUND_SUBSCRIPT_COLON
Verwenden Sie Leerzeichen um den Index-/Slice-Operator. Zum Beispiel:
my_list [ 1 : 10 : 2 ]
SPACES_AROUND_TUPLE_DELIMITERS
Fügt ein Leerzeichen nach dem öffnenden „(“ und vor dem endenden „)“-Tupeltrennzeichen ein.
( 1 , 2 , 3 )
wird wie folgt formatiert:
( 1 , 2 , 3 )
SPACES_BEFORE_COMMENT
Die Anzahl der Leerzeichen, die vor einem abschließenden Kommentar erforderlich sind. Dabei kann es sich um einen einzelnen Wert (der die Anzahl der Leerzeichen vor jedem nachgestellten Kommentar darstellt) oder um eine Werteliste (die Ausrichtungsspaltenwerte darstellt; nachgestellte Kommentare innerhalb eines Blocks werden an dem ersten Spaltenwert ausgerichtet, der größer als die maximale Zeilenlänge innerhalb des Blocks ist) handeln Block).
Hinweis: In einigen Kontexten (z. B. Shells oder Editor-Konfigurationsdateien) müssen Wertelisten möglicherweise in Anführungszeichen gesetzt werden.
Zum Beispiel mit
spaces_before_comment=5
:
1 + 1 # Adding values
wird wie folgt formatiert:
1 + 1 # Adding values <-- 5 spaces between the end of the statement and comment
mit
spaces_before_comment="15, 20"
:
1 + 1 # Adding values
two + two # More adding
longer_statement # This is a longer statement
short # This is a shorter statement
a_very_long_statement_that_extends_beyond_the_final_column # Comment
short # This is a shorter statement
wird wie folgt formatiert:
1 + 1 # Adding values <-- end of line comments in block aligned to col 15
two + two # More adding
longer_statement # This is a longer statement <-- end of line comments in block aligned to col 20
short # This is a shorter statement
a_very_long_statement_that_extends_beyond_the_final_column # Comment <-- the end of line comments are aligned based on the line length
short # This is a shorter statement
SPLIT_ALL_COMMA_SEPARATED_VALUES
Wenn sich eine durch Kommas getrennte Liste (
dict
,list
,tuple
oder functiondef
) in einer zu langen Zeile befindet, teilen Sie sie so auf, dass sich jedes Element in einer separaten Zeile befindet.
SPLIT_ALL_TOP_LEVEL_COMMA_SEPARATED_VALUES
Variation von
SPLIT_ALL_COMMA_SEPARATED_VALUES
, bei der, wenn ein Unterausdruck mit einem Komma in seine Startzeile passt, der Unterausdruck nicht geteilt wird. Dies vermeidet Aufteilungen wie die fürb
in diesem Code:
abcdef (
aReallyLongThing : int ,
b : [ Int ,
Int ])
Mit dem neuen Knopf wird dies wie folgt aufgeteilt:
abcdef (
aReallyLongThing : int ,
b : [ Int , Int ])
SPLIT_ARGUMENTS_WHEN_COMMA_TERMINATED
Vor Argumenten teilen, wenn die Argumentliste durch ein Komma abgeschlossen wird.
SPLIT_BEFORE_ARITHMETIC_OPERATOR
Auf
True
setzen, um die Aufteilung vor+
,-
,*
,/
,//
oder@
statt danach zu bevorzugen.
SPLIT_BEFORE_BITWISE_OPERATOR
Auf
True
setzen, um die Aufteilung vor&
,|
zu bevorzugen oder^
statt nachher.
SPLIT_BEFORE_CLOSING_BRACKET
Vor der schließenden Klammer teilen, wenn ein
list
oderdict
nicht in eine einzelne Zeile passt.
SPLIT_BEFORE_DICT_SET_GENERATOR
Split vor einem Wörterbuch oder Setgenerator (
comp_for
). Beachten Sie beispielsweise die Aufteilung vor demfor
:
foo = {
variable : 'Hello world, have a nice day!'
for variable in bar if variable != 42
}
SPLIT_BEFORE_DOT
Split vor dem
.
wenn wir einen längeren Ausdruck teilen müssen:
foo = ( 'This is a really long string: {}, {}, {}, {}' . format ( a , b , c , d ))
würde in etwa umformatieren:
foo = ( 'This is a really long string: {}, {}, {}, {}'
. format ( a , b , c , d ))
SPLIT_BEFORE_EXPRESSION_AFTER_OPENING_PAREN
Nach dem öffnenden Paren teilen, das einen Ausdruck umgibt, wenn er nicht in eine einzelne Zeile passt.
SPLIT_BEFORE_FIRST_ARGUMENT
Wenn eine Argument-/Parameterliste geteilt werden soll, dann teilen Sie sie vor dem ersten Argument.
SPLIT_BEFORE_LOGICAL_OPERATOR
Legen Sie den Wert auf
True
fest, um die Aufteilung vorand
oderor
statt nachher zu bevorzugen.
SPLIT_BEFORE_NAMED_ASSIGNS
Teilen Sie benannte Aufgaben auf einzelne Zeilen auf.
SPLIT_COMPLEX_COMPREHENSION
Für Listenverständnisse und Generatorausdrücke mit mehreren Klauseln (z. B. mehrere
for
Aufrufe,if
-Filterausdrücke) und die umgebrochen werden müssen, teilen Sie jede Klausel in eine eigene Zeile auf. Zum Beispiel:
result = [
a_var + b_var for a_var in xrange ( 1000 ) for b_var in xrange ( 1000 )
if a_var % b_var ]
würde in etwa umformatieren:
result = [
a_var + b_var
for a_var in xrange ( 1000 )
for b_var in xrange ( 1000 )
if a_var % b_var ]
SPLIT_PENALTY_AFTER_OPENING_BRACKET
Die Strafe für das Splitten direkt nach der Eröffnungsrunde.
SPLIT_PENALTY_AFTER_UNARY_OPERATOR
Die Strafe für die Teilung der Zeile nach einem unären Operator.
SPLIT_PENALTY_ARITHMETIC_OPERATOR
Der Nachteil der Aufteilung der Zeile um die Operatoren
+
,-
,*
,/
,//
,%
und@
.
SPLIT_PENALTY_BEFORE_IF_EXPR
Die Strafe für die Aufteilung direkt vor einem
if
-Ausdruck.
SPLIT_PENALTY_BITWISE_OPERATOR
Der Nachteil der Aufteilung der Linie um
&
,|
, und^
-Operatoren.
SPLIT_PENALTY_COMPREHENSION
Die Strafe für die Aufteilung eines Listenverständnisses oder Generatorausdrucks.
SPLIT_PENALTY_EXCESS_CHARACTER
Die Strafe für Zeichen, die das Spaltenlimit überschreiten.
SPLIT_PENALTY_FOR_ADDED_LINE_SPLIT
Die Strafe, die durch das Hinzufügen einer Zeilenaufteilung zur logischen Zeile entsteht. Je mehr Zeilenaufteilungen hinzugefügt wurden, desto höher war die Strafe.
SPLIT_PENALTY_IMPORT_NAMES
Der Nachteil der Aufteilung einer
import as
Namen. Zum Beispiel:
from a_very_long_or_indented_module_name_yada_yad import ( long_argument_1 ,
long_argument_2 ,
long_argument_3 )
würde in etwa umformatieren:
from a_very_long_or_indented_module_name_yada_yad import (
long_argument_1 , long_argument_2 , long_argument_3 )
SPLIT_PENALTY_LOGICAL_OPERATOR
Die Strafe für die Aufteilung der Zeile um die Operatoren „
and
“ undor
“ entsteht.
USE_TABS
Verwenden Sie zum Einrücken das Tabulatorzeichen.
YAPF gibt sich große Mühe, die Formatierung korrekt hinzubekommen. Bei manchen Codes ist die Qualität jedoch nicht so gut wie bei einer manuellen Formatierung. Insbesondere große Datenliterale können unter YAPF schrecklich entstellt werden.
Die Gründe dafür sind vielfältig. Kurz gesagt, YAPF ist einfach ein Werkzeug, das bei der Entwicklung hilft. Die Formatierung erfolgt so, dass sie mit dem Styleguide übereinstimmt, aber das ist möglicherweise nicht gleichbedeutend mit der Lesbarkeit.
Um diese Situation zu entschärfen, können Sie angeben, welche Regionen YAPF bei der Neuformatierung ignorieren sollte:
# yapf: disable
FOO = {
# ... some very large, complex data literal.
}
BAR = [
# ... another large data literal.
]
# yapf: enable
Sie können die Formatierung für ein einzelnes Literal auch wie folgt deaktivieren:
BAZ = {
( 1 , 2 , 3 , 4 ),
( 5 , 6 , 7 , 8 ),
( 9 , 10 , 11 , 12 ),
} # yapf: disable
Um die schönen dedented schließenden Klammern beizubehalten, verwenden Sie die dedent_closing_brackets
in Ihrem Stil. Beachten Sie, dass in diesem Fall alle Klammern, einschließlich Funktionsdefinitionen und Aufrufe, diesen Stil verwenden. Dies sorgt für Konsistenz in der gesamten formatierten Codebasis.
Wir wollten den Neuformatierungsalgorithmus von clang-format verwenden. Es ist sehr leistungsstark und darauf ausgelegt, die bestmögliche Formatierung zu erzielen. Bestehende Tools wurden mit unterschiedlichen Zielen entwickelt und erforderten umfangreiche Änderungen, um sie auf die Verwendung des Clang-Format-Algorithmus umzustellen.
Bitte! YAPF wurde sowohl für den Einsatz als Bibliothek als auch als Befehlszeilentool konzipiert. Das bedeutet, dass die Verwendung von YAPF für ein Tool oder IDE-Plugin kostenlos ist.
YAPF ist sehr bemüht, vollständig PEP 8-konform zu sein. Es ist jedoch von größter Bedeutung, dass Sie nicht riskieren, die Semantik Ihres Codes zu verändern. Daher versucht YAPF so sicher wie möglich zu sein und ändert den Token-Stream nicht (z. B. durch das Hinzufügen von Klammern). Alle diese Fälle können jedoch leicht manuell behoben werden. Zum Beispiel,
from my_package import my_function_1 , my_function_2 , my_function_3 , my_function_4 , my_function_5
FOO = my_variable_1 + my_variable_2 + my_variable_3 + my_variable_4 + my_variable_5 + my_variable_6 + my_variable_7 + my_variable_8
wird nicht geteilt, aber Sie können es leicht richtig machen, indem Sie einfach Klammern hinzufügen:
from my_package import ( my_function_1 , my_function_2 , my_function_3 ,
my_function_4 , my_function_5 )
FOO = ( my_variable_1 + my_variable_2 + my_variable_3 + my_variable_4 +
my_variable_5 + my_variable_6 + my_variable_7 + my_variable_8 )
Die Hauptdatenstruktur in YAPF ist das LogicalLine
Objekt. Es enthält eine Liste von FormatToken
s, die wir in einer einzelnen Zeile platzieren würden, wenn es keine Spaltenbeschränkung gäbe. Eine Ausnahme, bei der es sich um einen Kommentar in der Mitte einer Ausdrucksanweisung handelt, führt dazu, dass die Zeile in mehr als einer Zeile formatiert wird. Der Formatierer arbeitet jeweils an einem LogicalLine
-Objekt.
Eine LogicalLine
hat normalerweise keinen Einfluss auf die Formatierung der Zeilen davor oder danach. Es gibt einen Teil des Algorithmus, der zwei oder mehr LogicalLine
s zu einer Zeile verbinden kann. Beispielsweise kann eine Wenn-Dann-Anweisung mit einem kurzen Textkörper in einer einzelnen Zeile platziert werden:
if a == 42 : continue
Der Formatierungsalgorithmus von YAPF erstellt einen gewichteten Baum, der als Lösungsraum für den Algorithmus fungiert. Jeder Knoten im Baum stellt das Ergebnis einer Formatierungsentscheidung dar – dh, ob vor einem Token geteilt werden soll oder nicht. Mit jeder Formatierungsentscheidung sind Kosten verbunden. Daher werden die Kosten am Rand zwischen zwei Knoten realisiert. (In Wirklichkeit hat der gewichtete Baum keine separaten Kantenobjekte, sodass die Kosten bei den Knoten selbst liegen.)
Nehmen Sie zum Beispiel den folgenden Python-Codeausschnitt. Nehmen Sie für dieses Beispiel an, dass Zeile (1) gegen die Einschränkung der Spaltenbegrenzung verstößt und neu formatiert werden muss.
def xxxxxxxxxxx ( aaaaaaaaaaaa , bbbbbbbbb , cccccccc , dddddddd , eeeeee ): # 1
pass # 2
Für Zeile (1) erstellt der Algorithmus einen Baum, in dem jeder Knoten (ein FormattingDecisionState
-Objekt) den Status der Zeile an diesem Token darstellt, sofern die Entscheidung getroffen wurde, vor dem Token zu teilen oder nicht. Hinweis: Die FormatDecisionState
Objekte werden nach Wert kopiert, sodass jeder Knoten im Diagramm eindeutig ist und eine Änderung an einem keine Auswirkungen auf andere Knoten hat.
Heuristiken werden verwendet, um die Kosten einer Aufteilung oder Nichtaufteilung zu ermitteln. Da ein Knoten den Zustand des Baums bis zum Einfügen eines Tokens beibehält, kann er leicht feststellen, ob eine Aufteilungsentscheidung gegen eine der Stilanforderungen verstößt. Die Heuristik ist beispielsweise in der Lage, eine zusätzliche Strafe auf die Kante anzuwenden, wenn nicht zwischen dem vorherigen Token und dem hinzugefügten Token aufgeteilt wird.
Es gibt einige Fälle, in denen wir die Zeile niemals teilen wollen, da dies immer schädlich ist (dh es erfordert einen Backslash-Zeilenumbruch, was sehr selten wünschenswert ist). Für Zeile (1) möchten wir niemals die ersten drei Token aufteilen: def
, xxxxxxxxxxx
und (
. Wir möchten auch nicht zwischen )
und :
am Ende aufteilen. Diese Regionen gelten als „unzerbrechlich“. Dies spiegelt sich im Baum dadurch wider, dass es innerhalb des unzerbrechlichen Bereichs keine „geteilte“ Entscheidung (linker Zweig) gibt.
Nachdem wir nun den Baum haben, ermitteln wir die „beste“ Formatierung, indem wir den Pfad durch den Baum mit den geringsten Kosten finden.
Und das ist es!