YAPF는 clang-format
(Daniel Jasper가 개발)을 기반으로 하는 Python 포맷터입니다. 본질적으로 알고리즘은 코드를 가져와 구성된 스타일에 맞는 최상의 형식을 계산합니다. 코드를 유지 관리하는 데 드는 많은 수고를 덜어줍니다.
궁극적인 목표는 YAPF가 생성하는 코드가 프로그래머가 스타일 가이드를 따랐을 때 작성하는 코드만큼 좋은 것입니다.
참고 YAPF는 공식 Google 제품(실험용 또는 기타)이 아니며 Google이 소유한 코드일 뿐입니다.
PyPI에서 YAPF를 설치하려면:
$ pip install yapf
YAPF는 아직 "베타" 단계로 간주되며 출시된 버전은 자주 변경될 수 있습니다. 따라서 최신 개발 내용을 최신 상태로 유지하는 가장 좋은 방법은 이 저장소를 복제하거나 github에서 직접 설치하는 것입니다.
$ pip install git+https://github.com/google/yapf.git
YAPF를 라이브러리가 아닌 명령줄 도구로 사용하려는 경우 설치가 필요하지 않습니다. YAPF는 Python 인터프리터에 의한 디렉터리 실행을 지원합니다. YAPF를 DIR
에 복제/압축 해제한 경우 다음을 실행할 수 있습니다.
$ PYTHONPATH=DIR python DIR/yapf [options] ...
YAPF는 커뮤니티 확장 또는 플러그인을 통해 여러 편집자에서 지원됩니다. 자세한 내용은 편집기 지원을 참조하세요.
YAPF는 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
일반적으로 YAPF는 프로그램이 성공적으로 종료되면 0을 반환하고 그렇지 않으면 0이 아닌 값을 반환합니다.
--diff
제공되면 YAPF는 변경이 필요하지 않은 경우 0을 반환하고, 그렇지 않은 경우(프로그램 오류 포함) 0이 아닌 값을 반환합니다. CI 워크플로에서 이를 사용하여 코드가 YAPF 형식인지 테스트할 수 있습니다.
명령줄에 제공된 제외 패턴 외에도 YAPF는 YAPF가 호출되는 작업 디렉터리에 있는 .yapfignore
또는 pyproject.toml
파일에 지정된 추가 패턴을 찾습니다.
.yapfignore
구문은 UNIX의 파일 이름 패턴 일치와 유사합니다.
* matches everything
? matches any single character
[seq] matches any character in seq
[!seq] matches any character not in seq
./
로 시작하는 항목은 없어야 합니다.
pyproject.toml
사용하는 경우 제외 패턴은 [tool.yapfignore]
섹션의 ignore_patterns
키로 지정됩니다. 예를 들어:
[tool.yapfignore]
ignore_patterns = [
" temp/**/*.py " ,
" temp2/*.py "
]
YAPF에서 사용하는 형식 지정 스타일은 구성 가능하며 YAPF가 형식 지정을 수행하는 방법을 조정하는 데 사용할 수 있는 많은 "노브"가 있습니다. 전체 목록은 style.py
모듈을 참조하세요.
스타일을 제어하려면 --style
인수를 사용하여 YAPF를 실행하세요. 사전 정의된 스타일(예: pep8
또는 google
) 중 하나, 원하는 스타일을 지정하는 구성 파일의 경로 또는 키/값 쌍 사전을 허용합니다.
구성 파일은 [style]
제목이 있는 (대소문자를 구분하지 않는) key = value
쌍의 간단한 목록입니다. 예를 들어:
[style]
based_on_style = pep8
spaces_before_comment = 4
split_before_logical_operator = true
based_on_style
설정은 이 사용자 정의 스타일이 기반으로 하는 사전 정의된 스타일을 결정합니다(하위 클래스화와 유사하다고 생각함). 네 가지 스타일이 미리 정의되어 있습니다.
pep8
(기본값)google
(Google Python 스타일 가이드 기반)yapf
(Google 오픈소스 프로젝트에 사용)facebook
자세한 내용은 style.py
의 _STYLE_NAME_TO_FACTORY
참조하세요.
사전을 사용하여 명령줄에서 동일한 작업을 수행하는 것도 가능합니다. 예를 들어:
--style= ' {based_on_style: pep8, indent_width: 2} '
이는 pep8
기본 스타일을 사용하고 두 개의 공백 들여쓰기를 갖도록 수정합니다.
YAPF는 다음과 같은 방식으로 서식 스타일을 검색합니다.
.style.yapf
파일의 [style]
섹션.setup.cfg
파일의 [yapf]
섹션.pyproject.toml
파일의 [tool.yapf]
섹션.~/.config/yapf/style
파일의 [style]
섹션에 있습니다.해당 파일이 없으면 기본 스타일 PEP8이 사용됩니다.
YAPF가 수행할 수 있는 형식화 유형의 예는 다음과 같은 추악한 코드를 사용합니다.
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 ]
다음과 같이 다시 형식화합니다.
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 ]
YAPF 호출을 위한 두 가지 주요 API는 FormatCode
및 FormatFile
이며, 이들은 아래에 설명된 여러 인수를 공유합니다.
> >> 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
style_config
인수: 스타일 이름 또는 서식 스타일 설정이 포함된 파일 경로입니다. None이 지정되면 style.DEFAULT_STYLE_FACTORY
에 설정된 기본 스타일을 사용합니다.
> >> FormatCode ( "def g(): n return True" , style_config = 'pep8' )[ 0 ]
'def g(): n return True n '
lines
인수: 서식을 지정하려는 라인(ints), [start, end]의 튜플 목록입니다. 라인은 1부터 인덱스됩니다. 전체 파일이 아닌 코드 조각을 다시 포맷할 때 타사 코드(예: IDE)에서 사용할 수 있습니다.
> >> 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 '
print_diff
(bool): 다시 포맷된 소스를 반환하는 대신, 포맷된 소스를 다시 포맷된 소스로 바꾸는 diff를 반환합니다.
>>> print(FormatCode("a==b", filename="foo.py", print_diff=True)[0])
--- foo.py (original)
+++ foo.py (reformatted)
@@ -1 +1 @@
- a==b
+ a == b
참고: FormatCode
의 filename
인수는 diff에 삽입되는 것이며 기본값은 <unknown>
입니다.
FormatFile
전달된 파일에서 인코딩과 함께 형식이 변경된 코드를 반환합니다.
> >> 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
in_place
인수는 형식이 변경된 코드를 다시 파일에 저장합니다.
> >> FormatFile ( "foo.py" , in_place = True )[: 2 ]
( None , 'utf-8' )
> >> print ( open ( "foo.py" ). read ()) # contents of file (now fixed)
a == b
옵션:
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
닫는 괄호를 시각적인 들여쓰기에 맞춥니다.
ALLOW_MULTILINE_LAMBDAS
람다 형식을 두 줄 이상으로 지정할 수 있습니다.
ALLOW_MULTILINE_DICTIONARY_KEYS
사전 키가 여러 줄에 존재하도록 허용합니다. 예를 들어:
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
인수 목록에서 기본/명명 할당 이전에 분할을 허용합니다.
ALLOW_SPLIT_BEFORE_DICT_VALUE
사전 값 앞에 분할을 허용합니다.
ARITHMETIC_PRECEDENCE_INDICATION
공백이 연산자 우선 순위를 나타내도록 합니다. 예를 들어:
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
우선순위를 표시하기 위해 다음과 같은 형식이 지정됩니다.
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
최상위 함수 및 클래스 정의 주위에 원하는 빈 줄 수를 설정합니다. 예를 들어:
class Foo :
pass
# <------ having two blank lines here
# <------ is the default setting
class Bar :
pass
BLANK_LINE_BEFORE_CLASS_DOCSTRING
클래스 수준 독스트링 앞에 빈 줄을 삽입합니다.
BLANK_LINE_BEFORE_MODULE_DOCSTRING
모듈 독스트링 앞에 빈 줄을 삽입하세요.
BLANK_LINE_BEFORE_NESTED_CLASS_OR_DEF
다른
def
또는class
내에 바로 중첩된def
또는class
앞에 빈 줄을 삽입합니다. 예를 들어:
class Foo :
# <------ this blank line
def method ():
pass
BLANK_LINES_BETWEEN_TOP_LEVEL_IMPORTS_AND_VARIABLES
최상위 가져오기와 변수 정의 사이에 원하는 빈 줄 수를 설정합니다. isort와 같은 도구와의 호환성에 유용합니다.
COALESCE_BRACKETS
연속된 괄호를 분할하지 마십시오.
DEDENT_CLOSING_BRACKETS
또는INDENT_CLOSING_BRACKETS
설정된 경우에만 관련됩니다. 예를 들어:
call_func_that_takes_a_dict (
{
'key1' : 'value1' ,
'key2' : 'value2' ,
}
)
다음과 같이 형식을 변경합니다.
call_func_that_takes_a_dict ({
'key1' : 'value1' ,
'key2' : 'value2' ,
})
COLUMN_LIMIT
열 제한(또는 최대 줄 길이)
CONTINUATION_ALIGN_STYLE
연속 정렬을 위한 스타일입니다. 가능한 값은 다음과 같습니다.
SPACE
: 연속 정렬에는 공백을 사용합니다. 이는 기본 동작입니다.FIXED
: 연속 정렬을 위해 고정된 개수(CONTINUATION_INDENT_WIDTH
)의 열(예:CONTINUATION_INDENT_WIDTH
/INDENT_WIDTH
탭 또는CONTINUATION_INDENT_WIDTH
공백)을 사용합니다.VALIGN-RIGHT
: 연속선을 여러 개의INDENT_WIDTH
열에 수직으로 정렬합니다. 들여쓰기 문자로 연속 행을 수직으로 정렬할 수 없는 경우 약간 오른쪽(탭 하나 또는 공백 몇 개)입니다.
CONTINUATION_INDENT_WIDTH
줄 연속에 사용되는 들여쓰기 너비입니다.
DEDENT_CLOSING_BRACKETS
대괄호로 묶인 표현식이 한 줄에 들어갈 수 없는 경우에는 닫는 대괄호를 별도의 줄에 내어쓰기하여 넣습니다. 함수 정의 및 호출을 포함하여 모든 종류의 대괄호에 적용됩니다. 예를 들어:
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
목록이 쉼표로 끝나는 경우 각 목록 요소를 별도의 줄에 배치하는 경험적 방법을 비활성화합니다.
참고: 이 플래그의 동작은 v0.40.3에서 변경되었습니다. 이전에는 이 플래그가 true인 경우 후행 쉼표나 주석이 포함된 목록을 분할했습니다. 이제 목록에 주석이 포함될 때 분할을 제어하는
DISABLE_SPLIT_LIST_WITH_COMMENT
라는 별도의 플래그가 있습니다. 이전 동작을 얻으려면 두 플래그를 모두 true로 설정하세요. 자세한 내용은 CHANGELOG.md를 참조하세요.
DISABLE_SPLIT_LIST_WITH_COMMENT
삽입 댓글이 포함된 목록 내에서 모든 요소를 새 줄에 배치하지 마세요.
이 플래그가 없으면(기본값):
[ a, b, # c ]
이 플래그를 사용하면:
[ a, b, # c ]
이는 clang-format의 동작을 반영하며 목록에 있는 요소의 "논리적 그룹"을 형성하는 데 유용합니다. 함수 선언에서도 작동합니다.
EACH_DICT_ENTRY_ON_SEPARATE_LINE
각 사전 항목을 해당 줄에 배치합니다.
FORCE_MULTILINE_DICT
줄이
COLUMN_LIMIT
보다 짧더라도EACH_DICT_ENTRY_ON_SEPARATE_LINE
준수하세요.
I18N_COMMENT
국제화 주석에 대한 정규식입니다. 이 주석이 있으면 해당 줄의 형식이 다시 지정되지 않습니다. 주석은 번역된 문자열 옆에 있어야 하기 때문입니다.
I18N_FUNCTION_CALL
국제화 함수 호출 이름입니다. 이 함수가 있으면 해당 줄에서 형식 다시 지정이 중지됩니다. 왜냐하면 함수에 포함된 문자열은 i18n 주석에서 이동할 수 없기 때문입니다.
INDENT_BLANK_LINES
빈 줄보다는 들여쓰기된 빈 줄을 선호하려면
True
로 설정하세요.
INDENT_CLOSING_BRACKETS
괄호로 묶인 표현식이 한 줄에 들어갈 수 없는 경우 닫는 괄호를 별도의 줄에 들여쓰기하여 넣습니다. 함수 정의 및 호출을 포함하여 모든 종류의 대괄호에 적용됩니다. 예를 들어:
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
사전 키와 같은 줄에 들어갈 수 없는 경우 사전 값을 들여씁니다. 예를 들어:
config = {
'key1' :
'value1' ,
'key2' : value1 +
value2 ,
}
INDENT_WIDTH
들여쓰기에 사용할 열 수입니다.
JOIN_MULTIPLE_LINES
짧은 줄을 한 줄로 합칩니다. 예를 들어 한 줄의
if
문입니다.
NO_SPACES_AROUND_SELECTED_BINARY_OPERATORS
선택한 이항 연산자 주위에 공백을 포함하지 마십시오. 예를 들어:
1 + 2 * 3 - 4 / 5
*
,/
로 구성하면 다음과 같은 형식이 지정됩니다.
1 + 2 * 3 - 4 / 5
SPACE_BETWEEN_ENDING_COMMA_AND_CLOSING_BRACKET
목록 등의 끝 쉼표와 닫는 괄호 사이에 공백을 삽입합니다.
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
기본 인수나 키워드 인수에 대해 할당 연산자 주위에 공백을 선호하려면
True
로 설정합니다.
SPACES_AROUND_DICT_DELIMITERS
여는 '{' 뒤와 끝나는 '}' dict 구분 기호 앞에 공백을 추가합니다.
{ 1 : 2 }
다음과 같은 형식이 됩니다.
{ 1 : 2 }
SPACES_AROUND_LIST_DELIMITERS
여는 '[' 뒤와 끝나는 ']' 목록 구분 기호 앞에 공백을 추가합니다.
[ 1 , 2 ]
다음과 같은 형식이 됩니다.
[ 1 , 2 ]
SPACES_AROUND_POWER_OPERATOR
**
주변에 공백을 사용하려면True
로 설정하세요.
SPACES_AROUND_SUBSCRIPT_COLON
아래 첨자/슬라이스 연산자 주위에 공백을 사용하십시오. 예를 들어:
my_list [ 1 : 10 : 2 ]
SPACES_AROUND_TUPLE_DELIMITERS
여는 '(' 뒤와 끝나는 ')' 튜플 구분 기호 앞에 공백을 추가합니다.
( 1 , 2 , 3 )
다음과 같은 형식이 됩니다.
( 1 , 2 , 3 )
SPACES_BEFORE_COMMENT
후행 주석 앞에 필요한 공백 수입니다. 이는 단일 값(각 후행 주석 앞의 공백 수를 나타냄) 또는 값 목록(정렬 열 값을 나타냄)일 수 있습니다. 블록 내의 후행 주석은 블록 내의 최대 행 길이보다 큰 첫 번째 열 값에 정렬됩니다. 차단하다).
참고: 일부 상황에서는 값 목록을 인용해야 할 수도 있습니다(예: 셸 또는 편집기 구성 파일).
예를 들어
spaces_before_comment=5
사용하면 다음과 같습니다.
1 + 1 # Adding values
다음과 같은 형식이 됩니다.
1 + 1 # Adding values <-- 5 spaces between the end of the statement and comment
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
다음과 같은 형식이 됩니다.
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
쉼표로 구분된 목록(
dict
,list
,tuple
또는 functiondef
)이 너무 긴 줄에 있는 경우 각 요소가 별도의 줄에 있도록 분할하세요.
SPLIT_ALL_TOP_LEVEL_COMMA_SEPARATED_VALUES
SPLIT_ALL_COMMA_SEPARATED_VALUES
의 변형으로, 쉼표가 있는 하위 표현식이 시작 줄에 맞는 경우 하위 표현식이 분할되지 않습니다. 이렇게 하면 이 코드에서b
에 대한 것과 같은 분할을 방지할 수 있습니다.
abcdef (
aReallyLongThing : int ,
b : [ Int ,
Int ])
새로운 손잡이를 사용하면 다음과 같이 분할됩니다.
abcdef (
aReallyLongThing : int ,
b : [ Int , Int ])
SPLIT_ARGUMENTS_WHEN_COMMA_TERMINATED
인수 목록이 쉼표로 끝나는 경우 인수 앞에서 분할됩니다.
SPLIT_BEFORE_ARITHMETIC_OPERATOR
분할 이후보다
+
,-
,*
,/
,//
또는@
이전에 분할하는 것을 선호하려면True
로 설정하십시오.
SPLIT_BEFORE_BITWISE_OPERATOR
&
,|
이전에 분할을 선호하려면True
로 설정하세요. 또는 이후보다는^
.
SPLIT_BEFORE_CLOSING_BRACKET
list
이나dict
리터럴이 한 줄에 맞지 않으면 닫는 괄호 앞에서 분할합니다.
SPLIT_BEFORE_DICT_SET_GENERATOR
사전 또는 집합 생성기(
comp_for
) 이전에 분할됩니다. 예를 들어for
이전의 분할을 참고하세요.
foo = {
variable : 'Hello world, have a nice day!'
for variable in bar if variable != 42
}
SPLIT_BEFORE_DOT
.
더 긴 표현식을 분할해야 하는 경우:
foo = ( 'This is a really long string: {}, {}, {}, {}' . format ( a , b , c , d ))
다음과 같이 형식을 변경합니다.
foo = ( 'This is a really long string: {}, {}, {}, {}'
. format ( a , b , c , d ))
SPLIT_BEFORE_EXPRESSION_AFTER_OPENING_PAREN
한 줄에 맞지 않는 경우 표현식을 둘러싸는 여는 괄호 다음에 분할됩니다.
SPLIT_BEFORE_FIRST_ARGUMENT
인수/매개변수 목록을 분할하려는 경우 첫 번째 인수 전에 분할하세요.
SPLIT_BEFORE_LOGICAL_OPERATOR
이후보다 이전
and
또는or
분할을 선호하려면True
로 설정합니다.
SPLIT_BEFORE_NAMED_ASSIGNS
명명된 할당을 개별 줄로 분할합니다.
SPLIT_COMPLEX_COMPREHENSION
여러 절(예: 호출
for
다중,if
필터 표현식)이 있고 리플로우가 필요한 목록 이해 및 생성기 표현식의 경우 각 절을 자체 줄로 분할합니다. 예를 들어:
result = [
a_var + b_var for a_var in xrange ( 1000 ) for b_var in xrange ( 1000 )
if a_var % b_var ]
다음과 같이 형식을 변경합니다.
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
시작 대괄호 바로 다음에 분할하면 페널티가 발생합니다.
SPLIT_PENALTY_AFTER_UNARY_OPERATOR
단항 연산자 다음에 줄을 분할하면 페널티가 발생합니다.
SPLIT_PENALTY_ARITHMETIC_OPERATOR
+
,-
,*
,/
,//
,%
및@
연산자 주위로 선을 분할하면 페널티가 발생합니다.
SPLIT_PENALTY_BEFORE_IF_EXPR
if
표현식 직전에 분할하면 페널티가 발생합니다.
SPLIT_PENALTY_BITWISE_OPERATOR
&
주변의 선을 분할하면|
, 및^
연산자.
SPLIT_PENALTY_COMPREHENSION
목록 이해 또는 생성기 표현식을 분할하면 페널티가 발생합니다.
SPLIT_PENALTY_EXCESS_CHARACTER
열 제한을 초과하는 문자에 대한 페널티입니다.
SPLIT_PENALTY_FOR_ADDED_LINE_SPLIT
논리적 줄에 줄 분할을 추가하면 발생하는 페널티입니다. 라인 분할이 많을수록 페널티가 높아집니다.
SPLIT_PENALTY_IMPORT_NAMES
import as
분할하면 페널티가 발생합니다. 예를 들어:
from a_very_long_or_indented_module_name_yada_yad import ( long_argument_1 ,
long_argument_2 ,
long_argument_3 )
다음과 같이 형식을 변경합니다.
from a_very_long_or_indented_module_name_yada_yad import (
long_argument_1 , long_argument_2 , long_argument_3 )
SPLIT_PENALTY_LOGICAL_OPERATOR
and
및or
연산자 주변의 선을 분할하면 페널티가 발생합니다.
USE_TABS
들여쓰기에는 탭 문자를 사용하세요.
YAPF는 올바른 형식을 얻기 위해 매우 열심히 노력합니다. 그러나 일부 코드의 경우 직접 서식을 지정하는 것만큼 좋지 않습니다. 특히, 대규모 데이터 리터럴은 YAPF에서 끔찍하게 변형될 수 있습니다.
그 이유는 여러 가지입니다. 간단히 말해서 YAPF는 단순히 개발을 돕는 도구일 뿐입니다. 스타일 가이드와 일치하도록 형식을 지정하지만 이는 가독성과 동일하지 않을 수 있습니다.
이 상황을 완화하기 위해 수행할 수 있는 작업은 무언가를 다시 포맷할 때 YAPF가 무시해야 하는 영역을 나타내는 것입니다.
# yapf: disable
FOO = {
# ... some very large, complex data literal.
}
BAR = [
# ... another large data literal.
]
# yapf: enable
다음과 같이 단일 리터럴에 대한 형식 지정을 비활성화할 수도 있습니다.
BAZ = {
( 1 , 2 , 3 , 4 ),
( 5 , 6 , 7 , 8 ),
( 9 , 10 , 11 , 12 ),
} # yapf: disable
멋진 움푹 들어간 닫는 괄호를 유지하려면 스타일에 dedent_closing_brackets
를 사용하세요. 이 경우 함수 정의 및 호출을 포함한 모든 대괄호는 해당 스타일을 사용합니다. 이는 형식화된 코드베이스 전반에 걸쳐 일관성을 제공합니다.
우리는 clang-format의 재포맷 알고리즘을 사용하고 싶었습니다. 매우 강력하며 가능한 최상의 형식을 제공하도록 설계되었습니다. 기존 도구는 서로 다른 목표를 염두에 두고 만들어졌으며 clang-format의 알고리즘을 사용하도록 변환하려면 광범위한 수정이 필요합니다.
꼭 해주세요! YAPF는 명령줄 도구뿐만 아니라 라이브러리로도 사용되도록 설계되었습니다. 이는 도구나 IDE 플러그인이 YAPF를 자유롭게 사용할 수 있음을 의미합니다.
YAPF는 PEP 8을 완전히 준수하기 위해 매우 열심히 노력합니다. 그러나 코드의 의미가 변경될 위험을 피하는 것이 가장 중요합니다. 따라서 YAPF는 최대한 안전하려고 노력하며 토큰 스트림을 변경하지 않습니다(예: 괄호 추가). 그러나 이러한 모든 경우는 수동으로 쉽게 수정할 수 있습니다. 예를 들어,
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
분할되지는 않지만 괄호만 추가하면 쉽게 올바르게 표시할 수 있습니다.
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 )
YAPF의 주요 데이터 구조는 LogicalLine
객체입니다. 여기에는 열 제한이 없는 경우 한 줄에 배치하려는 FormatToken
s 목록이 있습니다. 표현식 문의 중간에 주석이 있는 경우는 예외로 해당 줄이 두 줄 이상으로 형식화됩니다. 포맷터는 한 번에 하나의 LogicalLine
객체에 대해 작동합니다.
LogicalLine
일반적으로 그 앞이나 뒤의 줄 형식에 영향을 주지 않습니다. 두 개 이상의 LogicalLine
을 하나의 라인으로 결합할 수 있는 알고리즘의 일부가 있습니다. 예를 들어, 짧은 본문이 포함된 if-then 문을 한 줄에 배치할 수 있습니다.
if a == 42 : continue
YAPF의 형식화 알고리즘은 알고리즘의 솔루션 공간 역할을 하는 가중치 트리를 생성합니다. 트리의 각 노드는 형식 결정의 결과, 즉 토큰 이전에 분할할지 여부를 나타냅니다. 각 형식 결정에는 그에 따른 비용이 따릅니다. 따라서 비용은 두 노드 사이의 가장자리에서 실현됩니다. (실제로 가중치가 부여된 트리에는 별도의 가장자리 개체가 없으므로 비용은 노드 자체에 있습니다.)
예를 들어 다음 Python 코드 조각을 살펴보겠습니다. 이 예에서는 라인 (1)이 열 제한 제한을 위반하여 형식을 다시 지정해야 한다고 가정합니다.
def xxxxxxxxxxx ( aaaaaaaaaaaa , bbbbbbbbb , cccccccc , dddddddd , eeeeee ): # 1
pass # 2
라인 (1)의 경우 알고리즘은 토큰 이전에 분할할지 여부를 결정한 경우 각 노드( FormattingDecisionState
개체)가 해당 토큰의 라인 상태인 트리를 구축합니다. 참고: FormatDecisionState
개체는 값별로 복사되므로 그래프의 각 노드는 고유하고 하나의 변경 사항이 다른 노드에 영향을 주지 않습니다.
휴리스틱은 분할 비용 또는 분할하지 않는 비용을 결정하는 데 사용됩니다. 노드는 토큰 삽입까지 트리 상태를 유지하므로 분할 결정이 스타일 요구 사항 중 하나를 위반하는지 쉽게 확인할 수 있습니다. 예를 들어, 휴리스틱은 이전 토큰과 추가되는 토큰이 분할되지 않을 때 가장자리에 추가 페널티를 적용할 수 있습니다.
줄을 분할하고 싶지 않은 경우도 있습니다. 그렇게 하면 항상 해로울 것이기 때문입니다(즉, 백슬래시-개행 문자가 필요하지만 이는 거의 바람직하지 않습니다). 라인 (1)의 경우 처음 세 개의 토큰 def
, xxxxxxxxxxx
및 (
분할하고 싶지 않을 것입니다. 끝에서 )
와 :
사이를 분할하고 싶지도 않을 것입니다. 이 영역은 "깨지지 않는다"고 합니다. 이는 깨지지 않는 영역 내에 "분할" 결정(왼쪽 분기)이 없기 때문에 트리에 반영됩니다.
이제 트리가 있으므로 비용이 가장 낮은 트리를 통해 경로를 찾아 "최상의" 형식이 무엇인지 결정합니다.
그리고 그게 다야!