Pep 8 코드 규칙

dev_pioneer07·2020년 10월 25일
0

안녕하세요 오늘은 많이 들어보셨을 pep8 에 대해서
간단히 나누려고 합니다.

이미 많은 블로그에서 언급된 주제고 그 블로그들과 비교하면
매우 부족하겠지만, 공식문서를 보고 간단히 정리해보면서 어떤 것을 알고 어떤 것을
모르는 지 스스로 점검하는 목적으로 포스팅을 하려고 합니다.

PEP 는 Python Enhance Proposal 로
파이썬을 개선하기 위한 개선 제안서이고 Python 코딩 스타일 가이드라인입니다.
가이드라인을 토대로 Team 개발 생산성과 유지보수성이 향상되기를 바랍니다.

1. 들여쓰기

4칸의 공백을 사용하기 : 괄호, if/else, class 등의 한 단위. Python 에서
암묵적으로 동의하는 포장된 요소는 수직 정렬해준다.

(Correct)

  • 구분 기호에 맞춰서 공백을 조정한다.
  • 인자 값은 나머지 코드와 구분되게끔 간격을 조정한다.
  • (옵션) 연속적인 라인에서 4 공백이 안지켜질 수도 있다.

(Wrong)

  • 수직 정렬이 맞지 않는 경우, 첫 번째 줄 인수 사용
  • 성격이 다른 나머지 코드와 구분되지 않는 정렬 방법

If Statement multiple lines

  • 조건문이 길어지는 경우 자연스러운 들여쓰기를 위해 한 칸, 추가 4칸 들여쓰기 가능
  • if 문 내부와 시각적인 혼란을 줄 수 있지만 명확한 지침은 없음. (Team Convention 에
    따름)

괄호, 삽입어구 multiple lines

  • 내부에 포함된 문자 아래에 정렬한다.
  • 시작하는 문자에 맞춰 정렬도 가능하다.

2. 탭 or Spaces

python3 에서는 Tab 과 spaces 혼용하는 것을 허용하지 않고,
python2 에서는 혼용을 허용하나, space 만 사용하기를 권장.

python2 혼용 방지를 위해 -t (경고), -tt(오류) 옵션 사용 가능

3. 라인 길이

모든 줄의 길이 제한은 79 자로 하고,
주석 등 Text 줄은 72자로 제한한다.

제한된 길이는 편집기 화면분할에서 작업을 용이하게 하지만,
코드 편집기가 오히려 가독성을 떨어뜨릴 수도 있다.

일부 개발팀들은 긴 라인을 선호하기도 하나,
다만 텍스트 문구는 72 제한을 지키도록 하자.

  • 주석을 최소화하고 명확하다면 더 좋겠죠?

표준 라이브러리는 위 규칙을 따르고 있다.

긴 줄을 사용하는 경우 괄호, 삽입어구를 적극 활용하고 백슬래쉬는 최소화하자.
물론 불가피한 경우는 백슬래쉬를 사용하자.

  • 유사한 경우로는 assert 구문이 있음

4. 이항 연산자 처리

지금까지는 이항 연산자 다음 개행하는 것이 일반적이었으나,
=> 추가 / 감산 되는 내용은 다음 내용이나 이전 내용에 머물러 가독성이 나쁨.

연산자가 앞에 나오는 구조를 사용하자. / 파이썬은 앞, 뒤 모두 허용

5. Blank Lines

최상위 함수, class 정의 부분에서는 2개의 공백 줄로 둘러싼다.
클래스 내의 메소드 정의에서는 1개의 공백 줄로 둘러싼다.

6. Source File Encoding

python의 배포 버전은 utf-8 encoding 을 따라야 한다.
(python2 는 ASCII 를 따름)

  • python3 버전에서는 흔히 사용하는 # -*- coding: utf-8 -*- 없이 한글 표시
    가능했던 것으로 기억합니다.
  • 그러나 표준 라이브러리의 모든 식별자는 반드시 ascii 전용 식별자 및 영어를 사용하게끔
    되어 있음.
  • 공식 라이브러리에 기여나 표준을 만들고자 하는 사람은 꾸준히 연습하는 것이 필요하겠죠?

7. Import

라이브러리를 import 하여 사용할 때 다른 성격의 파일은 라인을 구분해서
표기하는 것이 옳다.

# Correct
import os
import sys
# Wrong
import os, sys

그러나 같은 성격의 파일은 한 라인에 작성하는 것을 허용한다.

# OK
from subprocess import Popen, PIPE

모두 알다시피 import 는 모듈 설명, 문서 스트링 이후, 모든 전역, 상수 앞에 배치

  • 절대 경로가 더 나은 오류 메시지를 표시해주므로 권장된다.
  • 그러나 복잡한 패키지 레이아웃을 처리할 때는 상대 경로는 허용 가능
  • 표준 라이브러리에서는 절대 경로 import 가 필수
  • 와일드카드 가져오기 * 는 어떤 모듈을 사용하는 지 불확실하고 혼동을 줄 수 있어 피해야 함. (다만 public API 를 가져다가 재정의하고, 명확히 어떤 것이 정의되어야 하는 지 사전에
    정의되어 있지 않고 불명확한 경우에는 사용 가능)

8. Module Level Dunder Names

두 개의 선행, 후행 밑줄이 있는 이름
프로그램을 설명하는 변수는 dunder names 로 표시하자.

docstring 이후에 라이브러리 import 이전에 배치하자.

9. String Quotes

따옴표를 사용하든 쌍따옴표를 사용하든 결정하라.
다만 문자열의 백슬래시를 방지하기 위해서

세 개의 따옴표로 사용해서 가독성을 유지하라. 이 때는 쌍따옴표를 사용해서
pep 257 문서 문자열 규칙과 통일 시키는 것이 필요하다.

10. Whitespace in Expressions and Statements

불필요한 공백을 피하라.

다만 같은 공간에서 콜론(colon)은 이항 연산자와 같은 역할을 해서,
양쪽 모두 동일한 양을 가져야 한다. (이 때, 가장 낮은 우선순위)

  • 함수 호출
  • indexing 을 해줄 때

(Other Recommendations)

  • 기본적으로 공백은 발생하지 않도록 해라.
  • 표시한 연산자 주위에는 1칸의 공백을 유지하도록 하라. (=, +=, -=, == 등)
  • 다른 우선순위가 함께 사용되는 경우 낮은 연산자 주변에는 공백을 주고, 양 변에 동일하게 줄 수 있도록 하라.
  • arrow function 에서는 공백 주자.
  • 인자에 사용되는 '=' sign(Default 값) 에서는 공백 사용하지 마라.
  • 복합적으로 사용되는 경우는 공백을 주자.
  • 동일한 라인의 다중 문장은 권장되지 않는다.
  • 단일 if/for/while 문에서는 같은 줄에 작성해도 되나, 다중 구문에서는 절대 그러지 마라.

11. When to Use Trailing Commas

후행 쉼표는 option 이나, 튜플로 구성할 때는 필수 사항.
명확성을 위해 괄호 안에 후행 쉼표를 두자.

  • 버전 제어 관리, 시간이 지남에 따라 인수가 확장될 것으로 예상될 때 사용
  • 후행 쉼표를 추가하되, 닫힘 구분 기호와 같은 줄에 있는 것은 피하자. (싱글 튜플의 경우는 예외)

12. Comments

  • 코드에 맞는 주석을 달고 항상 최신 버전을 유지하자.
  • 완전한 문장을 갖추자
  • 소문자 식별자를 처음에 사용하는 것이 아니면 첫 번째 단어는 대문자로 쓰자.
  • 영어로 쓰자

(Block comments)

  • 들여쓰기는 동일한 수준으로
  • '#' 와 단일 공백으로 시작

(Inline Comments)

  • 코드 구문에서 최소 2 칸 이상으로 구분해야 함.
  • 마찬가지 # 와 단일 공백으로 시작
  • 웬만하면 사용하지 말자.

(Documentation Strings)

  • dunder name 위에 표기되는 문서 설명서
  • 모듈, 기능, 클래스를 설명해줄 때 사용. def 라인 뒤에 보통 쓰임
  • 문자열 종료 """ 은 자체 독립된 줄에 존재해야 한다.

13. Naming Conventions

완전한 일관성을 유지하기 힘듦.
참고만 하자. 지정된 표준을 따르는 것이 권장되지만 내부 일관성을 선호함.

  • 유저 사용에 적합한 것을 따르자는 것이 원칙

(Descriptive: Naming Styles)

(Prescriptive: Naming Conventions) 규범 : 명명규칙

  • 단일 문자 변수 이름으로 사용하지 말자. 알아보기 어려운 것은 피하자
  • 식별자는 ascii 호환이 되어야 한다.
  • 모듈은 짧은 소문자 이름, 제한된 _ 밑줄 사용이 가능하나, 패키지는 소문자만 사용 가능
  • C, C++ 로 작성된 확장 모듈이 있는 경우 선행 밑줄이 있는 경우가 있다.
  • [클래스] 이름은 CapWords 사용하고, 별도의 문서화 및 호출 가능한 경우 해당 명명 규칙을
    따를 수 있음. Built in name 의 경우 단일 단어로 구성된 경우도 있음.
  • [형식변수] CapWords 를 사용한다.
  • [예외] 클래스의 명명규칙을 따른다.
  • [전역 변수] 하나의 모듈 안에서만 사용을 권장. 글로벌 내보내기 방지를 위해 dunder 매커니즘을 사용. or 예전 컨벤션을 사용해서 전역변수 접두사에 밑줄을 사용하라.
  • [함수 및 변수 이름] lowercase 사용, 가독성 향상을 위해 밑줄로 구분 가능. 변수 이름도 동일한 규칙을 따르고. 이미 일반적인 경우는 그것을 따른다.
  • [함수, 메소드 인자] 인스턴스화 하는 경우 self 를 사용하고, 클래스 메소드 첫 번째
    인수를 cls 를 사용하라(?). 충돌할 경우 후행 밑줄을 추가하자.
  • [메소드 이름, 인스턴스 변수] 필요에 따라 밑줄로 구분된 단어가 포함된 이름 규칙 사용.
    공개되지 않은 변수, 인스턴스 변수에 선행 밑줄을 사용하라. sub class 와 충돌하지
    않기 위해서 두 개의 선행밑줄을 사용하라. 핵심은 이중 선행 밑줄은 하위 클래스 속성과
    충돌 방지하기 위해서 사용 필요
  • [상수] 모듈 수준에서 정의, 모두 대문자로 표시

(상속 디자인) : 별도로 공부해야 할듯

  • 웬만하면 비공개로 해라. 제3자가 비공유 속성을 바꾸지 못하도록.
    subclass api 는 다른 언어에서 보호된 으로 표기할 수 있다. 어떤 속성을 공개할 것인지
    결정하라.
    => 공공 속성은 선행 밑줄이 없어야 한다. 충돌하는 경우는 후행 밑줄 하나 추가(다른 잘못된 철자를 표현하는 것보다 나음)

(Public and Internal Interfaces)

  • 역호환성 보장은 공공 인터페이스에만 적용. 문서화되지 않는 인터페이스는 내부 인터페이스로
    간주되어야 한다.
  • 공개 api 정의 : __all__ 속성을 사용해서 정의하면 더 효과적.
  • __all__ 속성 정의 외 내부 인터페이스에는 하나의 선행 접두사를 붙여야 한다.
  • os.path, __init__ 과 같이 명시적으로 API 문서화가 되어 있지 않는 한 간접적인 액세스에 의존하면 안된다. (내부 인터페이스의 import 방식에 대해서 제대로 알지 못하는 듯 ㅠ)

14. Programming Recommendations

  • += b or a = a + b 구문이 안좋으며, 리프카운팅을 사용하지 않는 구현에서는 존재하지 않음.
  • 성능에 민감한 경우 .join() 양식을 대신 사용하는 것이 좋다. 선형 시간이 걸리도록 보장한다.
  • 'a' is not 이 not 'a' 보다 더 읽기 쉽다.
  • 다양한 비교를 통해 순서 연산?을 할 때 eq, ne, lt, le, gt, ge 을 사용하라.
  • functools.total_ordering 을 통해 비교할 수 있다.
  • 거울처럼 반사되는 용법을 사용할 수 있지만, 위 6개 용법을 통해 혼란을 없애라.
  • 람다 식 대신에 def 구문을 사용해라 (대부분 잘 사용하는 듯.) 할당 명세서를 통해 람다 사용을 최소화할 수 있다. 불명확하기 때문에 빼라고 이해.
  • BaseException(오류를 표시할 때 사용) 보다는 Exception 을 사용하라. 프로그래밍 적으로 어떻게 예외를 잘 포착할 수 있을 지 고민하고 오류를 발생시키는 경우는 'Error' 접미사 추가하라.
  • 예외 체인(raise X from Y)을 적절히 사용하라. 예외를 교체하는 경우
  • python 2, 3 예외 제기 시 raise ValueError('message') 를 사용하라. 예외 인수가 길 경우에 한 줄에 담을 필요는 없다.
  • try, except 문을 통해 예외를 잡자. except 구문만 단독적으로 사용하지 말자. 단독적으로 사용하는 경우는 프로그램 중단이 어렵고(ctrl-C) 모든 예외를 포착할 수 있다. except BaseException 과 같은 의미.
  • except 는 traceback 을 출력, 로깅해서 오류 발생했음을 알 수 있다. raise 로 상위 코드에 영향을 끼칠 수 있으니 try, finally 구문을 통해 핸들링하자.
  • except 이름 바인딩을 할 경우에는 정의된 것을 사용하자?
  • python 3.3 에는 명시적 예외 계층 구조가 있다.
  • try, except 구문에 포함된 내용을 최소화해서 목적을 분명히 하자.
  • 리소스가 로컬인 경우 with 구문을 사용해서 신속, 안정적으로 정리되도록 하자 try/finally 구문 허용
  • with 구문을 사용할 때는 기능을 세부적으로 나눠서 사용하자. 분명히 하자
  • 리턴 문장에서 일관성을 유지하라 아무것도 리턴하지 않는 경우는 None 으로 명확히 표기하자.
    함수 끝에도 반환문이 있어야 한다.
  • 문자열 모듈 대신 문자열 메소드를 사용하자
  • isinstance() 모듈 사용
profile
즐기면서 건강하게 개발하자

0개의 댓글