My Blog

Latest blog


What is the Shell and Shell Scripts?

 쉘 shell의 사전적 의미는 다음과 같습니다.
"the hard outer covering of some creatures"

Shell 'image by pixabay'

 컴퓨터에서 쉘도 비슷한 역할을 합니다. 운영체제의 커널(운영체제의 일부로서 컴퓨터의 메모리에 항상 떠있는 프로그램)을 감싸고 있습니다. 하지만 단순히 껍데기에 지나지 않고 유저와 커널을 연결시켜주는 다리 역할까지 합니다. 쉘은 대화창 형태의 인퍼테이스를 제공하며 사용자는 명령어를 사용하여 원하는 명령을 내릴 수 있습니다. 쉘은 이를 운영체제에 전달하고, 운영체제는 하드웨어가 이해할 수 있는 언어로 번역합니다. 하드웨어의 처리결과를 다시 사용자가 알아볼 수 있는 형태로 변경하여 화면으로 전달해 줍니다.

 쉘 스크립트 shell script의 기본 컨셉은 사용자의 명령어를 실행 순서대로 나열해 놓은 리스트 입니다.


Shell Types

 유닉스 Unix는 두 가지 타입의 쉘이 있습니다.
  1. 1. Bourne shell: '$'을 기본 프롬프트 기호로 사용함.
  2. 1. Bourne Again shell(bash): 1989년 브라이언 폭스 Brian Fox가 GNU 프로젝트를 위해 개발. 현재 리눅스의 표준 쉘.
  3. 2. Bourne shell(sh): 1977년 AT&T사의 벨 연구소에서 스티브 본이 Stephen Bourne 개발. 최초의 bourne shell.
  4. 3. Korn shell(ksh): 1983년 AT&T사의 벨 연구소에서 데이비드 콘 David Korn이 개발. sh를 기반으로 C 쉘의 많은 기능들을 추가함.
  5. 4. POSIX shell(sh)
  6. 2. C shell: C 언어 구문과 유사한 쉘. '%'를 기본 프롬프트 기호로 사용함.
  7. 1. C shell(csh): 1978년 버클리 대학의 빌 조이 Bill Joy가 개발.
  8. 2. TENEX/TOPS C shell(tcsh): 1983년 카네기 멜런 대학교의 켄 그리어 Ken Greer가 개발.


Google Shell Style Guide

 많은 구글러들에 의해 작성되고 수정되며 유지되는 가이드입니다. 원문은 이 곳에서 확인할 수 있습니다.


Background: Which Shell to Use

 유일하게 사용이 허용된 쉘 스크립트 언어는 bash입니다.

 실행파일은 반드시 '#!/bin/bash'로 시작해야 하며 최소한의 플래그 flag만 지녀야 합니다. 'set'으로 쉘 옵션을 설정하여 'bash [script_name]'과 같은 형식으로 스크립트를 호출해도 문제없이 실행되도록 합니다.

 실행 가능한 쉘 스크립트를 bash로 제한하는 것은 이미 모든 컴퓨터에 설치된 쉘 스크립트 언어이기 때문이며 이는 일관성을 갖도록 만들어 줍니다.

 단, 예외사항은 특정 패키지 사용을 위해 강제받을 때 다른 쉘 스크립트 언어를 사용할 수 있습니다. 예를 들어 'Solaris SVR4 packages'는 본 쉘의 사용이 필요합니다.


Background: When to use Shell

 쉘은 작은 유틸리티나 간단한 랩퍼 스크립트 wrapper scripts에만 사용해야 합니다.

 쉘 스크립트가 개발언어는 아니지만, 구글 전체적으로 다양한 유틸리티 스크립트를 작성하는데 사용됩니다. 이 스타일 가이드는 쉘 스크립트 언어가 범용적으로 사용되도록 어떻게 사용해야 하는지 그 방법을 제안하기 보다는 이것의 사용법을 인지시키는데 더 큰 목적이 있습니다.

 몇 가지 가이드라인을 우선 안내합니다.:
  • ⊙ 만약 당신이 대부분 다른 유틸리티를 호출하거나, 연관된 작은 데이터들을 다루는 작업을 한다면 쉘을 사용하는 것이 알맞습니다.
  • ⊙ 퍼포먼스가 중요하다면 쉘 말고 다른 것을 사용하세요.
  • ⊙ 만약 100 라인 이상 긴 스크립트를 사용하거나 직관적이지 않은 제어흐름 논리를 사용한다면, 좀 더 체계적인 언어를 사용해서 다시 작성해야 합니다. 스크립트의 길이는 계속 증가한다는 사실을 명심하세요. 하루라도 빨리 다른 언어를 사용하여 스크립트를 새로 작성하는 것이 나중에 더 많은 시간을 들여야 하는 불필요한 수고를 막는 길입니다.
  • ⊙ 코드의 복잡성을 평가할 때(다른 언어로 바꿀지 말지 결정하기 위해), 그 코드가 작성자가 아닌 다른 사람들이 쉽게 유지보수 할 수 있는지 따져봐야 합니다.


Shell Files and Interpreter Invocation: File Extensions

 실행파일은 확장자를 가지지 않거나(강력히 추천) '.sh' 확장자를 가져야 합니다. 라이브러리는 반드시 '.sh' 확장자를 가져야하며 그 자체로 실행할 수 없어야 합니다.

 프로그램이 실행될 때 어떤 언어로 쓰였는지 알 필요가 없고 쉘은 확장자를 필요로 하지 않으므로, 우리는 실행파일에 확장자를 사용하지 않는 것을 선호합니다.

 그러나 라이브러리는 어떤 언어로 쓰였는지 아는 것이 중요하고 때로는 다른 언어로 작성된 비슷한 라이브러리가 필요하기도 합니다. 따라서 동일한 목적을 가진, 그러나 다른 언어로 작성된 라이브러리 파일을 언어에 따른 접미사를 제외하고 동일한 파일명으로 정할 수 있습니다.


Shell Files and Interpreter Invocation: SUID/SGID

 SUID와 SGID는 쉘 스크립트에서 금지합니다. (*SUID, SGID는 root가 아닌 일반 user가 일시적으로 root의 권한을 사용할 수 있도록 설정하는 기능입니다.)

 쉘은 너무나도 많은 보안이슈들이 존재하므로 SUID/SGID를 허용하는 것이 거의 불가능합니다. 이런 이유로 bash는 SUID를 실행하기 어려우나 여전히 몇몇 플랫폼에서는 SUID를 사용하고 있으므로 이것의 사용을 명시적으로 금지합니다.

 필요한 경우 접근 권한을 제공하기 위해 'sudo'를 사용하세요.


Environment: STDOUT vs STDERR

 모든 에러 메시지는 'STDERR'로 보내야 합니다.

 이 방식은 실제 이슈로부터 일반적인 상태를 쉽게 분리할 수 있습니다.

 다른 상태 정보와 함께 에러 메시지를 보여주는 기능이 권장됩니다.

STDERR


Comments: File Header

 각 파일의 시작은 스크립트 내용에 대한 설명으로 시작합니다.

 모든 파일은 최상단에 스크립트 내용에 대한 간략한 요약 코멘트를 반드시 포함해야 합니다. 저작권 고지와 작성자 정보는 선택사항입니다.

File header


Comments: Function Comments

 명확하지 않으면서 길이가 짧은 함수는 모두 코멘트를 작성해야 합니다. 라이브러리에 포함되는 모든 함수는 길이나 복잡도에 상관없이 반드시 코멘트를 작성해야 합니다.

 코드를 모두 읽어보지 않고 코멘트(그리고 만약 제공된다면 도움말)를 읽는 것만으로도 누구든지 당신의 프로그램을 어떻게 사용하는지 배울 수 있거나 라이브러리 내의 함수를 사용할 수 있도록 만들 수 있어야 합니다.

 모든 함수 코멘트는 아래 요소들을 사용하여 API의 의도된 동작을 설명해야 합니다.

  • ⊙ Description of the function
  • ⊙ Globals: 사용되거나 한정된 전역변수 리스트
  • ⊙ Arguments: 인자
  • ⊙ Outputs: STDOUT이나 STDERR로의 출력
  • ⊙ Returns: 기본 종료상태 외 반환되는 값

Function comments


Comments: Implementation Comments

 코드에서 까다롭고 명확하지 않거나 흥미로운, 혹은 중요한 파트에 코멘트를 작성해야 합니다.

 일반적인 구글 코딩 코멘트 방식을 준수합니다. 모든 것에 코멘트를 작성하지 마세요. 만약 복잡한 알고리즘이나 평범하지 않은 무엇인가를 하고 있다면 짧은 코멘트를 작성합니다.


Comments: TODO Comments

 임시적인, 단기간 솔루션, 혹은 충분히 좋지만 완벽하지 않은 코드에 대해서 TODO 코멘트를 작성합니다.

 이것은 C++ Guide의 컨벤션과 일치합니다.

 TODO는 모두 대문자로 써야하며, TODO에 의해 참조된 문제에 대한 최상의 컨텍스트를 가진 사람의 이름, 이메일 주소, 혹은 다른 식별자를 붙여줘야 합니다. 이런 방식의 주요 목적은 일관성을 유지함으로써 이런 요청에 대해 더 자세한 내용들을 어떻게 찾아볼 수 있는지 검색 가능하도록 하기 위함입니다. TODO는 이것에 의해 참조된 사람이 꼭 그 문제를 해결해야 하는 것은 아닙니다. 그러므로 TODO를 사용할 때, 당신의 이름을 적어줘야 합니다.

TODO Comments


Formatting: Indentation

 수정중인 코드는 이미 적용되어 있는 스타일을 따라야 하지만, 새로운 코드에는 다음과 같은 내용을 적용합니다.

 들여쓰기는 스페이스 2개를 사용합니다. 탭 tab은 사용하지 않습니다.

 가독성을 높이기 위해 블럭 사이에는 빈 라인을 사용합니다. 들여쓰기는 스페이스 2개를 사용합니다. 탭 tab은 사용하지 않습니다. 이미 작성된 코드는 그 곳에서 사용하는 들여쓰기 방식을 따라야 합니다.


Formatting: Line Length and Long Strings

 한 개 라인의 최대 길이는 80자 입니다.

 만약 80자 이상 써야한다면 가능한 here 문서 또는 embedded newline을 사용합니다. 자연스럽게 분리할 수 없고 80자 이상 긴 리터럴 문자열 literal strings이라면 어쩔 수 없지만, 더 짧은 길이로 만드는 방법을 강력히 권장합니다.

Line Length and Long Strings


Formatting: Pipelines

 복수개의 파이프라인은 가능하면 모두 하나의 라인에 넣을 수 있도록 합니다.

 만약 불가능한 경우 2개의 공백 들여쓰기와 함께 파이프라인을 새로운 라인에 사용합니다. 연속적인 명령문인 경우 '|'를 사용하고 논리적인 단위인 경우 '||'와 '&&' 기호를 사용합니다.

Pipelines


Formatting: Loops

 '; do'와 '; then'을 'while', 'for', 'if'와 동일한 라인에 사용합니다.

 쉘에서 루프 loop는 약간 다르지만, 함수를 선언할 때 중괄호에 적용하는 것과 동일한 원칙을 따릅니다. 즉, '; do'와 '; then'은 if/for/while과 동일한 라인에 위치해야 합니다. 'else'와 닫는 구문 closing statements은 새로운 라인에 위치해야 하며 여는 구문과 수직으로 동일선상에 위치해야 합니다.

Loops


Formatting: Case statement

  • ⊙ 들여쓰기는 2개의 공백을 사용합니다.
  • ⊙ 하나의 라인에 모두 넣을 수 없을 때, 패턴 pattern의 닫는 괄호 다음과 ';;' 기호 이전에 1개의 공백을 사용합니다.
  • ⊙ 길이가 길거나 다중명령어인 경우 패턴 pattern, 동작 actions, 그리고 ';;' 기호를 각각 다른 라인에 위치 시킵니다.
 패턴 표현식은 'case'와 esac'에서 한 단계 들여쓰기 합니다. 다중라인 동작 Multiline actions은 한 단계 더 들여쓰기 합니다. 일반적으로 패턴 표현식에 인용부호는 필요하지 않고 여는 괄호도 사용하지 않습니다. ';&'와 ';;&' 표기법은 피하세요.

Case statement
 간단한 명령문은 가독성이 허용하는 한 패턴 pattern과 ';;' 기호를 동일라인에 사용합니다. 이런 방식은 종종 단일문자 옵션을 사용할 때 적합합니다. 동작 actions이 동일라인에 적합하지 않은 경우 모두 분리된 라인에 위치시키며, 동일라인에 사용하는 경우 패턴 pattern의 닫는 괄호 다음과 ';;' 기호 이전에 각각 1개의 공백을 사용합니다.

Case statement of Simple commands


Formatting: Variable expansion

 우선순위: 일관성을 유지하세요; 변수에 인용부호를 사용하세요; "$var"보다는 "${var}"가 선호되는 방식입니다.

 다음 가이드라인은 강력히 권장하지만 필수 제약사항은 아닙니다. 가능하면 권장하는 방식을 사용하세요.

 우선순위 순서대로 정리해보면,
  • ⊙ 이미 코드에 규칙이 존재하는 경우 일관성을 지키세요.
  • ⊙ 변수에 인용부호를 사용하세요.
  • ⊙ 강력히 필요하거나 막심한 혼동을 피하기 위한 목적이 아닌 이상 단일문자 쉘 스페셜 single character shell specials/위치 매개변수 positional parameters에는 중괄호를 사용하지 않습니다. 다른 모든 변수에는 중괄호 사용이 선호됩니다.

Variable expansion


Formatting: Quoting

 인용부호를 제외한 확장이 필요하지 않거나 쉘 내부 정수가 아닌 경우라면 변수, 대체 명령어, 공백, 또는 쉘 메타 문자를 포함한 문자열은 항상 인용부호를 사용합니다.

 명령어 라인 플래그와 같은 리스트 요소의 안전한 인용부호 적용을 위해서 배열을 사용합니다.

 정수로 정의되는 쉘 내부 읽기전용 특수 변수('$?', '$#', '$$', '$!')는 선택적으로 인용부호를 사용합니다.

 (명령어 옵션이나 경로명과 달리) "단어"인 문자열에 인용부호 사용을 선호합니다.

 Literal integers에는 절대로 인용부호를 사용하지 않습니다.

 [[ ... ]] 패턴 매치 규칙에 인용부호를 사용할 때는 주의하세요.

 메시지나 로그의 문자열에 단순히 인자들을 추가할 때와 같이 '$*'를 사용하는 특별한 이유가 없는 한 '$@'를 사용합니다.


Quoting


Features and Bugs - ShellCheck

 ShellCheck project는 여러분이 작성한 쉘 스크립트의 일반적인 버그와 경고메시지를 확인합니다. 쉘 스크립트 길이와 상관없이 모두 이 과정을 거치도록 권장합니다.


Features and Bugs - Command Substitution

 Backticks(`) 대신에 $(command)를 사용하세요.

 중첩된 backticks를 사용하는 경우 escaping을 위해서 내부 backticks에 '\' 기호를 사용합니다. 하지만 $(command) 포맷은 중첩 되더라도 있는 그대로 사용할 수 있으며 가독성 또한 좋습니다.


Command Substitution


Features and Bugs - Test, [ ... ], and [[ ... ]]

 '[ ... ]', test, '/usr/bin/[' 방식보다 '[[ ... ]]' 방식을 선호합니다.

 '[[ ... ]]' 방식은 경로명 확장자가 존재하지 않는 에러나 '[['와 ']]' 사이에서 일어나는 단어 분리와 같은 에러를 줄여줍니다. 또한 '[ ... ]' 방식은 정규표현식이 허용되지 않는 반면 '[[ ... ]]' 방식은 허용됩니다.


'[[ ... ]]'


Features and Bugs - Testing Strings

 가능하면 문자열 필터 대신 인용부호를 사용하세요.

 Bash는 테스트에서 빈 문자열을 다루기 충분할 정도로 똑똑합니다. 따라서 코드를 테스트를 할 때 문자열 필터 대신 빈 문자열/비어있지 않은 문자열을 사용하세요. 이것은 코드 가독성 또한 높여줍니다.


Testing strings 1

 테스트 대상에 대한 혼동을 피하기 위해서 명시적으로 '-z'와 '-n' 옵션을 사용하세요.

 동일하다는 의미를 표현할 때 '='와 '==' 두 가지 방식 모두 작동하지만, 명확성을 위해 '=='를 사용하세요. 그러나 '[[ ... ]]' 안에서 '<' 기호와 '>' 기호를 사용할 때 주의하세요. 대신 '(( ... ))' 방식이나 '-lt', '-gt'와 같은 방식을 사용합니다.


Testing strings 2


Features and Bugs - Wildcard Expansion of Filenames

 파일명 확장자에 와일드카드를 사용할 때 분명한 경로를 사용하세요.

 파일명이 '-' 기호로 시작될 수 있는 경우 와일드카드 확장에 './*'를 사용하는 것이 '*'를 사용하는 것보다 훨씬 안전합니다.


Wildcard expansion of filenames

Features and Bugs - Eval

 'eval'은 피해야 합니다.

 변수에 input을 할당할 때 'eval'을 사용하면 input을 흐트려 뜨립니다. 또한 그 변수가 과거에 어떤 상태였는지 확인과정을 거치지 않고서도 설정할 수 있도록 만들 수 있습니다.


Eval


Features and Bugs - Arrays

 인용부호 관련 문제를 피하기 위해서 리스트 요소들을 저장할 때 bash 배열을 사용합니다. 이 방식은 특히 인자 리스트에 적용해야 합니다. 보다 복잡한 데이터 구조를 쉽게 만들기 위해 배열을 사용해서는 안됩니다.


Arrays

 배열의 장점
 배열을 사용하면 인용부호 의미의 혼동 없이 문자열 내용들을 나열할 수 있습니다. 반대로 배열을 사용하지 않으면 문자열 안에서 중첩된 인용부호 사용과 같은 잘못된 시도로 이어질 수 있습니다.
 배열을 사용하면 공백을 포함한 문자열, 임의의 문자열에 대한 시퀀스/리스트를 안전하게 저장할 수 있습니다.

 배열의 단점
 배열을 사용하면 스크립트의 복잡도가 증가할 수 있습니다.

 배열의 결정
 리스트를 안전하게 생성하고 전달하기 위해서 배열을 사용해야 합니다. 특히 명령어 인수들을 작성할 때 혼동되는 인용부호 문제를 피하기 위해 배열을 사용해야 합니다. 배열에 접근하기 위해서는 인용부호 확장- "${array[@]}" -을 사용하세요. 그러나 더욱 숙련된 데이터 처리가 요구된다면 쉘 스크립팅을 사용하지 말아야 합니다.


Features and Bugs - Pipes to While

 'while'에 파이프를 사용하는 것보다 대체 프로세스를 사용하거나 builtin(bash4+) readarray를 사용하세요. 파이프는 서브쉘을 만드는데 파이프라인 안에서 일어나는 그 어떤 변수의 수정작업도 부모쉘에 전파되지 않습니다.

 파이프 안 'while'에 대한 서브쉘은 추적하기 어려운 미묘한 버그들을 초래할 수 있습니다.

 대체 프로세스를 사용하는 방법도 서브쉘을 만듭니다. 하지만 서브쉘 내부에 'while' (혹은 다른 어떤 명령어)을 사용하지 않고서도 서브쉘로부터 'while'로 리다이렉션을 허용합니다.

 또는 파일을 읽고 배열로 만든 뒤 배열 안 내용들을 반복하며 도는 builtin readarray를 사용하세요.


Pipes to while


Features and Bugs - Arithmetic

 'let', '$[ ... ]', 'expr'보다 '(( ... ))'나 '$(( ... ))' 방식을 사용합니다.

 '$[ ... ]'나 'expr', 'let'은 절대 사용하지 않습니다.

 '<'나 '>' 기호는 '[[ ... ]]' 표현식 안에서 수치비교 기능을 할 수 없습니다. 모든 숫자 비교 작업에서는 '[[ ... ]]' 방식을 사용하지 말고 '(( ... ))' 방식을 사용합니다.


Arithmetic


Naming Conventions - Function Names

 함수명은 소문자로 이루어지고 단어 사이 밑줄로 구분합니다. 라이브러리는 '::' 기호로 분리합니다. 함수명 다음에 괄호가 필요합니다. 키워드 'function'은 선택사항이지만 프로젝트 전반에 걸쳐 일관성을 가져야 합니다.

 만약 여러분이 하나의 함수를 작성한다면, 소문자를 사용하고 단어 사이 밑줄을 사용해서 분리하세요. 만약 패키지를 작성한다면 '::' 기호와 함께 패키지 이름을 분리하세요. 중괄호는 반드시 함수명과 동일 라인에 위치해야 하며 함수명과 괄호 사이에 공백은 넣지 않습니다.


Function names


Naming Conventions - Variable Names

 변수명도 함수명과 동일합니다.

 루프를 돌기 위한 변수명은 루프 대상 변수와 비슷하게 만들어야 합니다.


Variable names


Naming Conventions - Constants and Environment Variable Names

 상수 및 환경변수명은 모두 대문자로 이루어지고 단어 사이 밑줄로 구분하며 파일 상단에 선언합니다.


Constant and environment variable names


Naming Conventions - Source Filenames

 소스파일명은 소문자를 사용하고 단어 사이 밑줄로 구분합니다.

 예를들어, maketemplate나 make_template를 사용하되 make-template는 사용하지 않습니다.


Naming Conventions - Read-only Variables

 대상 변수들이 '읽기전용'이라는 사실을 확실히 하기 위해서 'readonly'나 'decalre -r'을 사용합니다.

 전역변수는 쉘 내부에서 광범위하게 사용되므로 에러를 잡아내는 것이 중요합니다. 만약 당신이 read-only 변수를 선언했다면 명확하게 표현하세요.


Read-only Variables


Naming Conventions - Use Local Variables

 특정 함수와 관련된 변수를 선언할 때 'local'을 사용하세요. 선언과 할당은 서로 다른 라인에 위치해야 합니다.

 지역변수를 선언할 때는 'local'을 사용하여 오직 함수 안에서, 그리고 그 하위 항목에서만 보이도록 합니다. 이런 방식은 전역변수 공간을 오염시키는 것을 방지하고 함수 밖에서 중요할지도 모르는 변수를 무심결에 설정하는 것을 방지합니다.

 대체 명령어에 의해 값이 할당될 때 선언과 할당은 각각 분리된 라인에 위치해야 합니다; Builtin local은 대체 명령어로부터 종료 코드를 전파하지 않습니다.

Use local variables


Naming Conventions - Function Location

 파일 내 모든 함수는 상수 바로 아래에 함께 위치시킵니다. 함수 사이에 실행 가능한 코드를 숨기지 않습니다. 그런 방식은 코드를 파악하기 어렵게 만들며 그 결과 디버깅 할 때 나쁜 결과를 초래합니다.


Naming Conventions - main

 스크립트가 1개 이상의 함수를 포함할 정도로 길이가 길면 'main' 함수가 필요합니다.

 프로그램의 시작점을 쉽게 찾도록 하기 위해서 'main' 함수를 가장 아래에 넣습니다. 코멘트가 없는 파일의 가장 마지막 라인은 'main' 함수를 호출합니다.


Calling Commands - Checking Return Values

 항상 리턴값을 체크합니다. 그리고 리턴값은 유용한 정보를 제공해야 합니다.

 파이프를 사용하지 않은 명령문에서 '$?'를 사용하거나 'if'문을 사용하여 간단히 리턴값을 직접 확인합니다.


Checking return values


Conclusion

 상식적인 선에서 일관성을 유지하세요.


Opinion

 파이썬 스타일 가이드(PEP8)에 이어 이번에는 구글에서 사용하는 쉘 스크립트 스타일 가이드를 살펴봤습니다. 그동안 쉘 스크립트는 리눅스에서 NGS data 분석을 위한 프로그램 실행과 자동화 코드를 생성하는데 사용했습니다. 별다른 컨벤션 없이 필요한 기능을 검색하며 규칙없이 사용했는데 앞으로는 구글 스타일 가이드에 따라 코드를 만들도록 노력해야 겠습니다.


파이썬 이해하기

생각이나 느낌을 나타내거나 전달하기 위하여 사용하는 음성, 문자, 몸짓 등의 수단 또는 그 사회관습적 체계

언어의 사전적 정의입니다.
언어란 한 사회의 구성원들 사이에 약속된 의사소통 규칙이자 오랜 세월 특유의 문화와 역사가 담긴 사회관습적 체계입니다.

누구나 모국어를 비롯해 외국어를 학습해 본 경험이 적어도 한번 즈음 있을 것입니다. 여러분들은 어떤식으로 접근하셨나요? 사회 구성원들과 생활하며 자연스럽게 익히기도 합니다. 단어와 문법을 차근차근 공부하며 체계적으로 언어에 대한 지식을 쌓아가기도 합니다. 어떤 방식을 사용하던지 최종 목표는 언어에 담긴 철학을 이해하고 자유롭게 구사하여 의사소통을 하는 것입니다.

프로그래밍 언어도 마찬가지입니다.
파이썬을 사용해서 코드를 작성하고 다른 사람과 의사소통 하려면 먼저 파이썬을 온전히 이해해야 합니다. 파이썬이 지나고 있는 철학은 무엇일까요?

Readability counts.

PEP20: The Zen of Python에서 19개 문장으로 파이썬의 철학을 설명하고 있습니다. 한 마디로 요약하면 Readability! 어느 누가 봐도 읽기 쉽고 간결한 파이썬 코드를 지향하고 있습니다.


PEP8은 무엇인가요?

파이썬 관련 문서를 검색하다보면 PEP라는 단어가 자주 출몰합니다. PEP는 'Python Enhancement Proposals'의 약자로 '파이썬 제안 사항' 정도로 이해할 수 있습니다. 파이썬의 새로운 기능이나 적용사항을 안내하거나, 일반적인 가이드라인이나 정보를 제공하는 역할을 담당합니다.

PEP8은 파이썬 창시자인 Guido van Rossum을 비롯하여 총 세 명의 저자가 작성했으며 Style Guide for Python Code에 대한 내용을 담고 있습니다. 일종의 코드 규칙을 제안함으로써 파이썬 코딩 컨벤션 Python coding convention 역할을 담당하고 있습니다. 이 외 다양한 파이썬 스타일 가이드 대부분 PEP8을 기반으로 하고 있으므로 반드시 알아두는 것이 좋습니다. PEP8 공식문서에서 세부내용을 확인할 수 있습니다.


A Foolish Consistency is the Hobgoblin of Little Minds

미국의 철학자이자 시인으로 활동한 Ralph Waldo Emerson의 'Self-Reliance'에 나오는 문장입니다. 원문은 아래와 같습니다.

"A foolish consistency is the hobgoblin of little minds, adored by little statesmen and philosophers and divines."

"어리석은 일관성은 별 볼 일 없는 정치가와 철학자, 그리고 신학자들이 사랑하는 편협한 마음을 가진 홉고블린이다." 

앞/뒤 문맥을 살펴보면 Emerson은 오늘 하는 말과 내일 하는 말이 모순될 지언정 다른 사람의 시선에 휘둘리지 말고 스스로 신뢰하는 자세가 사회를 지탱하고 더 나은 방향으로 나아가도록 만든다고 이야기 합니다. 사회의 정해진 규칙과 다른 사람이 옳다고 여기는 기준에 맞춰 바보같이 사는 것은 짓궃은 장난을 잘하는, 소인배 홉고블린에 지나지 않는다는 의미입니다. 이 사상은 오늘날 미국의 기둥이 된 개인주의 정신의 근간이 되었습니다.

파이썬 코드에서 가독성은 매우 중요합니다. 그러나 반드시 PEP8이 제시하는 가이드에 얽매일 필요는 없습니다. 더 가독성이 뛰어난 방식이 있다면 묻지도 따지지도 말고 그 방식을 선택하세요.


Code Lay-out: Indentation

하나의 indentation 레벨은 4개의 spaces를 사용합니다.

연속되는 라인은  괄호/중괄호/대괄호 내부에서 파이썬의 implicit line joining을 사용하여 래핑된 요소의 수직선 상에 맞추거나 hanging indent를 사용합니다. Hanging indent를 사용할 때는 첫 번째 라인에 인자들이 넣지 않습니다. 또한 예외적으로 4-space 규칙을 벗어날 수 있습니다. ( 예를 들어 2-space로 대체 )


PEP8: Indentation I

'if'문과 같은 조건문의 조건이 충분히 길어지는 경우, 괄호를 사용하여 멀티라인으로 작성합니다. 마찬가지로 4-space 규칙이 기본 적용되며 경우에 따라 추가 indent를 사용합니다.


PEP8: Indentation II

닫는 괄호/중괄호/대괄호는 멀티라인 중 마지막 라인의 첫 번째 글자와 동일선상에 맞추거나, 첫 번째 라인의 시작과 동일선상에 맞춥니다.


PEP8: Indentation III


Code Lay-out: Tabs or Spaces?

Space가 선호되는 방식입니다.

Tab을 사용하는 경우는 이미 코드에서 indent가 tab으로 작성된 경우입니다. 파이썬3에서는 space와 tab 혼용을 금지하고, 파이썬2에서는 혼용이 가능하지만 tab을 모두 space로 변환할 것을 강력히 권고합니다.


Code Lay-out: Maximum Line Length

모든 라인은 최대 79자 이내로 제한합니다.
Docstrings나 comments 같은 몇몇 구조들에서는 최대 72자로 제한합니다.

글자수를 제한하면 두 개 이상 코드를 editor로 열어서 동시에 작업할 수 있습니다. 눈으로 보기에도 더 깔끔한 코드를 작성할 수 있습니다.

멀티라인으로 작성할 경우 앞서서 언급한 indent 규칙을 준수하고 backslash를 사용합니다.

PEP8: Maximum Line Length


Code Lay-out: Should a Line Break Before or After a Binary Operator?

사칙연산기호와 라인 브레이크의 위치에 관한 내용입니다.
과거에는 사칙연산기호 이후에 라인 브레이크가 위치하는 스타일을 권장했습니다. 하지만 다음 두 가지 이유로 가독성을 떨어뜨립니다. 첫 번째로 연산기호들이 라인마다 다른 위치로 흩어집니다. 두 번째로 연산기호의 대상을 명확히 파악하기 어렵습니다. 아래 예시를 함께 보세요.


PEP8: Wrong! Line break and binary operator

하지만 수학에서는 전통적으로 사칙연산기호 이전에 라인 브레이크가 위치하는 스타일을 사용합니다. 가독성이 더 좋은 이 방식을 파이썬에서도 권장합니다.

PEP8: Correct! Line break and binary operator


Code Lay-out: Blank Lines

최상위 레벨 함수와 클래스 정의는 두 개의 공백라인으로 둘러쌉니다.

클래스 내부의 메서드 정의는 한 개의 공백라인으로 둘러쌉니다.

추가 공백라인은 관련된 함수들끼리 그룹으로 분리하는데 (아껴서) 사용할 수 있습니다.

추가 공백라인은 함수 내에서도 논리적 섹션을 나타내기 위해 (아껴서) 사용할 수 있습니다.


Code Lay-out: Source File Encoding

파이썬 배포판의 코드는 파이썬3인 경우 UTF-8, 파이썬2인 경우 ASCII를 사용합니다.
모든 파이썬 표준 라이브러리는 반드시 ASCII 식별자를 사용해야하고 언제나 사용 가능한 영어 단어를 사용합니다.
또한 테스트 케이스, 코드 작성자 이름 등과 같은 예외사항을 제외하면 모든 코드 내 문자와 코멘트는 ASCII를 사용합니다.


Code Lay-out: Imports

Import는 보통 라인별로 분리해서 진행합니다.

PEP8: Imports I

Import는 항상 파일의 제일 첫 부분에, 모듈 코멘트와 docstrings 바로 다음에, 그리고 모듈 전역변수와 상수 전에 위치해야 합니다.

다음 순서에 따라 그룹화 되어야 합니다.
  • 1. 표준 라이브러리 imports
  • 2. 연관된 써드 파티 third party imports
  • 3. 로컬 응용프로그램/라이브러리 imports
각 그룹 사이에는 공백라인 한 개를 넣습니다.


Code Lay-out: Module Level Dunder Names

__all__, __author__, __version__ 등과 같은 모듈 레벨 "dunders" (두 개의 underbar가 앞/뒤 각각 붙는 명칭)는 모듈 docstring 이후 'from __future__' import를 제외한 다른 import문 이전에 위치해야 합니다.

PEP8: Module level dunder names


String Quotes

파이썬에서 작은따옴표와 큰따옴표는 동일하므로 어느 것을 권장하지 않습니다. 하지만 한 가지를 선택해서 사용하는 방식을 고수합니다.

PEP257의 내용에 다라 삼중따옴표는 항상 큰따옴표를 사용합니다.


Whitespace in Expressions and Statements: Pet Peeves

Pet Peeves의 의미를 영영사전에서 찾아보면, "Something that is maybe a bit annoying to most people but is very annoying or upsetting to a particular person."으로 설명하고 있습니다. 애완동물(Pet)이 대부분 사람들(most people)에게는 덜 짜증나는(a bit annoying) 존재이지만 특정 사람(particular person)에게는 매우 짜증나는 존재일 수 있습니다. 공백에 관한 규칙도 사소한 내용이지만 세세한 부분이 들어있다보니 누군가에게는 성가신 규칙이 될 수 있겠죠?

그럼에도 불구하고 아래와 같은 상황에서 추가적인 공백은 피하세요.

PEP8: Pet Peeves


Whitespace in Expressions and Statements: Other Recommendations

공백을 길게 늘려 사용하는 것은 대개 잘 보이지 않고 혼란을 초래할 수 있으니 피하세요.

다음 이진연산기호들은 항상 단일 공백으로 둘러쌉니다: 할당(=), 증강할당(+=, -=, etc), 비교(==, <, >, !=, <>, <=, >=, in, not in, is, is not), 논리(and, or, not)

만약 서로 다른 우선순위를 갖는 연산자들을 사용하면 가장 낮은 우선순위를 갖는 연산자를 공백으로 둘러쌉니다. 스스로 판단하되 한 개 이상의 공백은 절대 사용하지 말고 언제나 이진 연산자의 양 쪽 모두 같은 양의 공백을 사용합니다.

PEP8: Other recommendations I

함수 주석은 콜론에 대한 일반 규칙을 사용하고 -> 화살표가 있다면 항상 주위에 공백을 넣어야 합니다.

PEP8: Other recommendations II

키워드 인수나 기본 매개변수 값을 나타낼 때 사용하는 '=' 기호 주위에 공백을 사용하지 않습니다. 그러나 인자에 기본값을 할당할 때 사용하는 '=' 기호 주위에는 공백을 사용합니다.

PEP8: Other recommendations III

복합 명령문(한 라인에 여러개 명령문을 사용)은 사용하지 마세요.

PEP8: Other recommendations IV


When to Use Trailing Commas

후행 콤마는 요소가 한 개인 튜플을 생성할 때 필수인 경우를 제외하면 보통 선택사항입니다. 그리고 버전 제어 시스템이 사용될 때, 값이나 인자, 또는 임포트 된 항목들이 시간이 지남에 따라 확장될 것으로 추정될 때 도움이 됩니다. 사용방법은 각각의 값을 하나의 라인에 배치하고 항상 후행 콤마를 붙인 뒤 닫는 괄호/중괄호/대괄호를 다음 라인에 넣습니다.

PEP8: Trailing commas


Comments

코드와 모순되는 코멘트를 사용하느니 차라리 없는 것이 더 낫습니다. 언제나 코드가 변경될 때마다 코멘트를 최신으로 유지하는데 우선순위를 둬야합니다.

코멘트는 완성된 문장으로 작성해야 합니다. 첫 번째 글자는 대문자를 사용해야 하지만 식별자인 경우 소문자를 사용합니다.

블럭 코멘트 Block comments는 보통 완전한 문장으로 구성된 하나 이상의 단락으로 구성되며 각 문장은 마침표로 끝냅니다.

멀티- 문장 코멘트 내부에서는 각 문장이 끝날 때마다 두 개의 공백을 사용합니다. 단, 마지막 문장 다음에는 사용하지 않습니다.

영어를 사용할 때는 'Strunk and White'를 준수합니다. ('Strunk and White'는 영어작문의 기본서와 같은 'The Elements of Style(EOS)'을 지칭하는 단어입니다. 코넬 대학의 William Strunk Jr. 교수가 영문과 수업에 사용하기 위해 유인물 형태로 제작했는데 점점 대학교재처럼 사용되었습니다. Strunk 교수가 세상을 떠나고 그의 제자인 E. B. White가 이를 정식 책으로 출간하여 오늘날까지 미국 대학생들의 영어작문 기본서 역할을 하고 있습니다. 내용은 이 곳에 공개되어 있습니다.)

비영어권 파이썬 개발자들에게: 당신이 작성한 코드를 다른 나라 사람들이 절대 보지 않을 것이란 120% 확신이 없다면 코멘트를 영어로 작성하세요.


Comments: Block Comments

블럭 코멘트는 일반적으로 코멘트에 이어지는 일부 (또는 모든) 코드에 적용되며 그 코드와 동일한 레벨로 indent를 사용합니다. 각 라인은 '#'과 한 개의 공백으로 시작합니다. (코멘트 내부에 들여쓰기 된 텍스트는 제외)

블럭 코멘트 내부의 단락은 한 개의 '#'을 포함하는 라인으로 분리됩니다.


Comments: Inline Comments

인라인 코멘트 Inline comments는 아껴가며 사용하세요.

인라인 코멘트는 코드와 같은 라인에 존재하는 코멘트 입니다. 인라인 코멘트는 적어도 두 개 이상의 공백으로 코드와 분리되어야 하며 '#'과 한 개의 공백으로 시작합니다.

사실 인라인 코멘트는 필요하지 않고 명백한 내용을 명시하면 산만해 집니다. 이런 경우 사용하지 마세요.


Comments: Documentation Strings

좋은 docstring을 작성하기 위한 컨벤션은 PEP257에 영원히 남아있습니다.

모든 공개된 모듈, 함수, 클래스, 그리고 메서드에 대한 docstring을 작성하세요. 비공개 메서드는 작성할 필요는 없지만 어떤 역할을 하는지 정도는 코멘트로 작성해 주세요. 이 코멘트는 'def' 라인 다음에 나와야 합니다.

PEP257은 좋은 docstring 컨벤션에 대해 기술하고 있습니다. 가장 중요한 내용은 멀티라인 docstring의 끝에 나오는 """ 기호는 별도의 라인에 독립적으로 사용해야 한다는 것입니다. 단일라인 docstring은 """ 기호를 같은 라인에 사용합니다.

PEP8: Docstring


Naming Conventions

파이썬 라이브러리의 명명 컨벤션은 약간 엉망이므로 완전히 일관성을 유지할 수 없습니다. 그럼에도 불구하고 현재 권장되는 명명 기준을 소개합니다.


Naming Conventions: Overriding Principle

API의 공개적인 파트로써 이용자에게 보이는 명칭은 구현보다 사용방법을 반영하는 컨벤션을 준수합니다.


Naming Conventions: Descriptive - Naming Styles

정말 다양한 명명 스타일이 존재합니다.

명명 스타일은 보통 아래와 같이 구분됩니다.
  • ⊙ b (single lowercase letter)
  • ⊙ B (single uppercase letter)
  • ⊙ lowercase
  • ⊙ lower_case_with_underscores
  • ⊙ UPPERCASE
  • ⊙ UPPER_CASE_WITH_UNDERSCORES
  • ⊙ CapitalizedWords: 또는 CapWords, CamelCase, StudlyCaps 등으로 불립니다. 울퉁불퉁한 모양 때문에 그런 이름이 붙었습니다.
  • ⊙ MixedCase: 첫 글자가 lowercase라는 점에서 CapitalizedWords와 차이가 있습니다.
  • ⊙ Capitalized_Words_With_Underscores: 못 생겼죠!

또한 연관된 이름을 그룹으로 묶기 위한 짧은 고유 접두사를 사용하는 스타일도 있습니다. 예를 들어 os.start() 함수는 st_mode, st_size, st_mtime 등의 이름을 가지는 아이템들을 튜플 형태로 반환합니다.

추가로 선행/후행 underscore를 사용하는 아래와 같은 형태로도 사용합니다. (일반적으로 어떤 컨벤션과도 함께 조합해서 사용할 수 있습니다.)
  • ⊙ _single_leading_underscore: 약한"internal use"를 나타냅니다. 예를들어 'from M import *'는 underscore로 시작하는 이름을 가진 객체를 import하지 않습니다.
  • ⊙ single_trailing_underscore_: 파이썬 키워드와 충돌을 피하기 위해 사용됩니다. 예를들어 'Tkinter.Toplevel(master, class_='ClassName')'
  • ⊙ __double_leading_underscore: 클래스 속성을 명명할 때 name mangling을 호출합니다. (클래스 'FooBar' 내부에서 '__boo'는 '_FooBar__boo'가 됩니다.
  • ⊙ __double_leading_and_trailing_underscore__: "magic" 객체 또는 사용자-제어 네임스페이스에 활성화 되어있는 속성에 사용합니다. 예를들어 '__init__', '__import__', 또는 '__file__'가 있으며 절대 동일한 이름을 사용하면 안됩니다.


Naming Conventions: Prescriptive - Names to Avoid

'l', 'O', 'I'는 단일 문자 변수명으로 절대 사용하지 않습니다.

일부 폰트에서 위 문자들은 숫자 '0', '1'과 구분이 불가능 할 수 있습니다.


Naming Conventions: Prescriptive - ASCII Compatibility

PEP3131의 정책 섹션에서 기술하는 것처럼 기본 라이브러리에서 사용하는 구분자는 반드시 ASCII와 호환 가능해야 합니다.


Naming Conventions: Prescriptive - Package and Module Names

모듈명은 모두 lowercase로 이루어진 짧은 이름을 가져야 합니다. 가독성을 향상시킬 수 있다면 모듈명에 underscore를 사용할 수 있습니다. 파이썬 패키지도 또한 마찬가지 규칙을 가지지만 underscore를 사용하지 않도록 권장합니다.

C나 C++로 작성된 확장 모듈이 높은 수준(예를들어 더 객체지향적인)의 인터페이스를 동반할 때, C/C+= 모듈은 선행 underscore를 가집니다. (예를들어 '_socker)

Naming Conventions: Prescriptive - Class Names

클래스 이름은 보통 CapWords 컨벤션을 준수합니다.

인터페이스가 문서화되어있고 주로 호출 가능한 형태로 사용되는 경우 함수들에 대한 명명 컨벤션이 대신 사용될 수 있습니다.

내장 함수들에 대한 별도의 컨벤션이 존재함을 기억하세요. 대부분 내장함수 명명은 하나의 단어 (혹은 함께 실행되는 두 개의 단어)로 이루어져 있습니다. 그러나 오직 예외 명명과 내장 상수들에서는 CapWords 컨벤션이 사용됩니다.


Naming Conventions: Prescriptive - Type Variable Names

PEP484에서 가져온 자료형 변수의 명명은 일반적으로 짧은 CapWords 사용을 선호합니다: T, AnyStr, Num. covariant나 contravariant behavior을 정의하려고 사용된 변수에는 각각 접미사 '_co', '_contra'를 사용할 것을 권장합니다.

PEP8: Type variable names


Naming Conventions: Prescriptive - Exception Names

예외는 클래스이므로 클래스 명명 컨벤션이 적용됩니다. 하지만 예외가 정말 error를 나타내는 예외명에 접미사 "Error"를 사용합니다.


Naming Conventions: Prescriptive - Global Variable Names

(전역 변수들이 오직 하나의 모듈 내에서만 사용하는 것으로 정해져 있기를 바라며) 함수들에 대한 동일한 명명 컨벤션이 적용됩니다.

'from M import *' 형태로 사용되도록 디자인 된 모듈은 전역 변수들을 내보내는 것을 방지하기 위해 '__all__' 메카니즘을 사용하거나, 혹은 전역변수에 underscore를 접두사로 사용하는 옛날 컨벤션을 사용해야 합니다.


Naming Conventions: Prescriptive - Function and Variable Names

함수명은 lowercase로 구성되어야 하며 가독성을 향상시키기 위해 단어는 underscore로 분리되어야 합니다.

mixedCase는 하위 버전과 호환성을 유지하기 위해 이미 잘 알려진 스타일 (예를들어 threading.py)의 컨텍스트 내부에서만 허용됩니다.


Naming Conventions: Prescriptive - Function and Method Arguments

인스턴스 메서드의 첫 번째 인자는 항상 'self'를 사용합니다.

클래서 메서드의 첫 번째 인자는 항상 'cls'를 사용합니다.

만약 함수의 인자명이 이미 예약된 키워드와 충돌한다면 약어나 스펠링을 망가뜨리는 것보다는 한 개의 후행 underscore를 추가하는 것이 일반적으로 더 낫습니다. 그러므로 'class_'가 'clss'보다 낫습니다. (이보다 더 좋은 방법은 동의어를 사용해서 충돌을 피하는 것입니다.)


Naming Conventions: Prescriptive - Method Names and Instance Variables

함수 명명 규칙을 사용하세요: 가독성을 향상시키기 위해 lowercase의 단어들은 iunderscore로 분리합니다.

비공개 메서드와 인스턴스 변수에는 오직 한 개의 선행 underscore만 사용합니다.

서브클래스와의 충돌을 피하기 위해서 두 개의 선행 underscore를 사용하여 파이썬의 name mangling 규칙을 호출합니다.

파이썬은 다음과 같은 이름을 클래스명으로 변환합니다: 만약 클래스 'Foo'가 '__a'라는 속성을 가지고 있다면 'Foo.__a' 방식으로 접근할 수 없습니다. ('Foo._Foo__a' 방식으로 강제적으로 접근할 수는 있습니다.) 일반적으로 두 개의 선행 underscore는 서브클래스로 디자인 된 클래스 안에서의 속성과 이름 충돌을 피하기 위한 목적으로만 사용해야 합니다.


Naming Conventions: Prescriptive - Constants

상수는 보통 모듈 수준에서 정의됩니다. 그리고 단어들은 underscore로 분리된 대문자를 사용합니다. 예를들어 'MAX_OVERFLOW', 'TOTAL'


Naming Conventions: Prescriptive - Designing for Inheritance

언제나 클래스의 메서드와 인스턴스 변수(통칭하여 "속성")의 공개/비공개 여부를 결정하세요. 만약 판단이 잘 서지 않는다면 비공개로 선택하세요; 비공개를 공개로 만드는 것이 더 쉽습니다.

공개 속성은 클래스와 상관없는 클라이언트가 사용할 것으로 기대되는 속성이며 하위 속성과 호환되지 않는 변경은 피하도록 약속해야 합니다. 비공개 속성은 써드파티에 의해 사용될 것으로 기대되지 않는 속성입니다; 비공개 속성은 변경되거나 심지어 삭제될 수 있습니다.

여기에서 "private"란 용어는 사용하지 않았으며, 실제로 파이썬에는 "private" 속성이 없기 때문입니다.

다른 속성의 범주는 "subclass API" (다른 언어에서는 종종 "protected"라고 불림)의 일부 파트가 되는 것입니다. 일부 클래스는 상속을 통해 클래스의 기능적인 측면을 확장하거나 수정해서 사용하도록 디자인 되었습니다. 그런 클래스를 디자인 할 때 어떤 속성이 공개인지, 어떤 속성이 subclass API인지, 그리고 어떤 속성시 정말 기본 클래스에 의해서만 사용되는지 정확하게 판단해야 합니다.

이를 명심하고 다음 파이썬다운 가이드라인을 참고하세요.
  • ⊙ 공개 속성은 선행 underscore를 가지지 않습니다.
  • ⊙ 만약 함수의 인자명이 이미 예약된 키워드와 충돌한다면 약어나 스펠링을 망가뜨리는 것보다는 한 개의 후행 underscore를 추가하는 것이 일반적으로 더 낫습니다. (하지만 이런 규칙이 있음에도 불구하고 'cls'는 클래스로 알려진 임의의 변수나 인자, 특히 클래스 메서드의 첫 번째 인자에 대한 명칭으로 사용됩니다.)
    주의1: 클래서 메서드에 대해 앞에서 본 인자명 권장사항을 참고하세요.
  • ⊙ 간단한 공개 자료 속성에 대해서 복잡한 접근자/변경자 메서드를 사용하지 않고 단지 속성명만 표시하는 것이 가장 좋습니다. 파이썬은 미래를 향한 개선을 위해 손쉬운 방법을 제공한다는 것을 기억한다면, 단순한 자료의 속성이 기능적 동작을 늘려가야 함을 알게 될 것입니다. 그런 경우 단순한 자료의 속성 접근구문 뒤에 프로퍼티를 사용하여 기능구현을 숨기세요.

    주의1: 프로퍼티는 오직 새로운 스타일 클래스에만 작동합니다.

    주의2: 비록 캐싱caching과 같은 사이드이펙트가 일반적으로 괜찮더라도 기능적 동작이 사이드이펙트로부터 자유로울 수 있도록 관리하려고 노력해야 합니다.

    주의3: 계산비용이 많으 드는 프로퍼티 사용은 피해야 합니다; 속성 표기는 호출자가 접근이 쉽다고 믿도록 만듭니다.

    만약 클래스가 서브클래스로 예약되어 있고 서브클래스에서 사용되지 않기를 바라는 속성이 있다면, 후행 underscore가 아니라 두 개의 선행 underscore를 사용해서 명명하는 것을 고려합니다. 이 방식은 파이썬의 name mangling 알고리즘을 호출하고 클래스명이 속성명으로 바뀝니다. 이는 속성명이 우연히 동일한 이름의 속성을 포함하고 있는 서브클래스와 충돌하는 것을 피하도록 도와줍니다.

    주의1: 오직 단순한 클래스명만이 변경된 이름으로 사용된다는 것을 기억하세요. 따라서 만약 서브클래스가 동일한 클래스명과 속성명을 선택한다면 여전히 이름이 충돌할 수 있습니다.

    주의2: Name mangling은 디버깅과 '__getattr__()'과 같은 류의 사용을 약간 불편하게 만들 수 있습니다. 그러나 name mangling 알고리즘은 문서화가 잘 되어있고 수동으로 쉽게 수행할 수 있습니다.

    주의3: 모두가 name mangling을 좋아하지는 않습니다. 우연치않게 맞이하는 이름 충돌을 피해야 할 필요성과 숙련된 호출자에 의한 잠재적인 사용 가운데 균형을 맞추도록 노력해야 합니다.


Naming Conventions: Public and Internal Interfaces

모든 하위 호환성 보장은 단지 공용 인터페이스에만 적용됩니다. 따라서 사용자가 공용과 내부 인터페이스를 명확히 구별할 수 있는 것이 중요합니다.

문서에서 명시적으로 하위 호환성 보증으로부터 제외되는 임시 또는 내부 인터페이스로 분명하게 명시하지 않는 한, 문서화된 인터페이스는 공용으로 간주합니다. 문서화되지 않은 모든 인터페이스는 내부용으로 가정해야 합니다.

내부검사를 더 잘 지원하기 위해서 모듈은 '__all__' 속성을 사용하는 공개 API에서 이름을 확실하게 선언해야 합니다. '__all__'을 비어있는 리스트로 설정하는 것은 모듈에 공개 API가 없음을 나타냅니다.

'__all__'을 알맞게 설정하더라도 내부 인터페이스(패키지, 모듈, 클래스, 함수, 속성, 혹은 다른 이름)는 여전히 하나의 선행 underscore로 시작해야 합니다.

인터페이스가 포함하고 있는 어떤 네임스페이스(패키지, 모듈, 또는 클래스)가 내부 인터페이스로 간주된다면, 인터페이스도 내부 인퍼테이스로 간주합니다.

Import 된 이름은 언제나 세세한 구현을 고려해야 합니다. 다른 모듈이 포함된 모듈의 API에서 명시적으로 문서화 된 부분, 예를들어 os.path 또는 하위 모듈로부터 기능성이 노출된 패키지의 '__init__'과 같은 모듈, 이 아닌 이상 이렇게 import 된 이름에 대한 간접적인 접근에 의존해서는 안됩니다.


Programming Recommendations

다른 파이썬(PyPy, Jython, IronPython, CPython, Psyco 등과 같은) 구현에 불리하지 않은 방식으로 코드를 작성해야 합니다.

예를들어 'a += b' 또는 'a = a + b' 형식에서 CPython의 효과적인 내부 문자열 연결 구현에 의존하지 않습니다. 이 최적화는 CPython 안에서조차 깨지기 쉽고(이것은 오직 몇 가지 형태에 대해서만 작동합니다.) refcounting을 사용하지 않는 구현에서는 전혀 존재하지 않습니다. 대신 라이브러리에서 성능에 민감한 부분에서는 '.join' 형식을 사용합니다.이것은 다양한 구현에서 연결에 소요되는 시간이 일정하도록 보장합니다.

None과 같은 싱글레톤singletons과의 비교는 언제나 'is' 또는 'is not'을 사용합니다. 절대 평등연산자를 사용하지 않습니다.

'not ... is'보다 'is not' 연산자를 사용합니다. 기능적으로 동일한 표현이지만 후자가 가독성이 좋고 더 선호되는 방식입니다.

PEP8: Programming recommendations I

다양한 비교와 함께 순서 나열하기 작업을 진행할 때, 오직 특정 비교만 실행하는 다른 코드에 의존하기보다 6개의 연산자('__eq__', '__ne__', '__lt__', '__le__', '__gt__', '__ge__')를 모두 구현하는 것이 가장 좋습니다.

식별자에 바로 람다 표현식을 붙이는 할당구문 대신 항상 'def' 구문을 사용합니다.

PEP8: Programming recommendations II

BaseException 보다 Exception으로부터 예외를 유도합니다. BaseException으로부터의 직접적인 상속은 예외를 발견하는 것이 대부분 잘못되는 경우를 위해 미리 예약되어 있습니다.

파이썬2에서 에러를 발생시킬 때, 예전 방식인 'raise ValueError, message' 대신에 'ValueError(message)'를 사용합니다.

'try/except' 절에서 'try' 절은 코드에서 최소로 제한합니다. 이 방식은 버그가 숨겨지는 것을 방지합니다.

PEP8: Programming recommendations III

'return' 구문은 일관성을 가져야 합니다. 함수에서 모든 'return'문이 표현식을 반환하거나, 모두 아무것도 반환하지 않거나 해야합니다. 만약 표현식을 반환한다면 값이 없는 'return'문은 'return None'을 반환해야 합니다. 그리고 'return'문은 가능하다면 명시적으로 함수의 가장 마지막에 위치합니다.

PEP8: Programming recommendations IV

접두사나 접미사를 체크하려면 문자열 슬라이싱 대신 ".startswith()"와 ".endswith()"를 사용합니다.