간단한 파이썬 코딩 스탠다드

Table of Content

본 문서는 Python Software Foundation의 pep-8번 문서를 번역, 요약, 수정한 문서입니다.모든 라이센스나와 저작권은 원본문서를 따릅니다. C 로 구현하는 파이썬의 경우 pep-7 번 문서를 참조 바랍니다.


들여쓰기 : 들여쓰기 레벨 당 4 스페이스로 들여씁니다.

연속적인 줄을 정렬하는 경우 줄 안의
Wrapping 된 요소 (Ex. (var1 a, var2) ) 는 수평으로 정렬해야 합니다. 또한 줄 들여쓰기로 코드가 이어지는 경우 첫 라인에는 매개변수가 와서는 안됩니다. 첫 라인 이후부터는 추가적인 들여쓰기를 통해 코드가 이어짐을 명확히 표현하는 것이 좋습니다.

다음의 예시를 참조하세요.

옳은 예:

# 매개변수를 한줄에 나열할 수 없는 경우, 여는 괄호를 기준으로 정렬
foo = long_function_name(var_one, var_two,
                         var_three, var_four)
# 추가적인 들여쓰기(def로부터 2번의 추가적인 탭이 들어갑니다.)를 하고 매개변수를 
# 두 번째 라인으로 들여쓰기 하여 표현
def long_function_name(
        var_one, var_two, var_three,
        var_four):
    print(var_one)
# 추가적인 들여쓰기로 이어지는 코드의 정렬
foo = long_function_name(
    var_one, var_two,
    var_three, var_four)

나쁜 예:

나쁜 예:
# 수평 정렬 하지 않는 경우엔 첫 줄에 매개변수가 오지 않습니다.
foo = long_function_name(var_one, var_two,
    var_three, var_four)
# 추가적인 들여쓰기로 매개변수 정의 줄임을 명확히 해야 합니다.
def long_function_name(
    var_one, var_two, var_three,
    var_four):
    print(var_one)

선택사항:

선택사항:
# 추가적인 들여쓰기 없음
if (this_is_one_thing and
    that_is_another_thing):
    do_something()
if (this_is_one_thing and
    that_is_another_thing):
    # Since both conditions are true, we can frobnicate.
    do_something()
# 조건절이 길어지는 경우 들여쓰기를 추가로 해도 무방하다.
if (this_is_one_thing
        and that_is_another_thing):
    do_something()

[], {},()로 만드는 리스트나 배열 등은 줄바꿈 시 처음 등장하는 공백이 아닌 문자에 맞춰 정렬합니다.

my_list = [
    1, 2, 3,
    4, 5, 6,
]
result = some_function_that_takes_arguments(
    'a', 'b', 'c',
    'd', 'e', 'f',
)
my_list = [
    1, 2, 3,
    4, 5, 6,
]
result = some_function_that_takes_arguments(
    'a', 'b', 'c',
    'd', 'e', 'f',
)

탭과 스페이스

스페이스가 탭보다 선호됩니다. 탭은 기존에 탭으로 들여쓰기 되어있는 코드들을 위해서만 동작합니다. Python3의 경우 탭과 스페이스를 혼용하여 들여쓰기 하는 것을 허용하지 않습니다. 2 역시 스페이스로 변환을 거쳐야 합니다.


최대 라인 길이

몇몇 환경과의 호환성을 위해 (Ex. 터미널) 최대 79자로 모든 길이를 제한합니다. 주석이나 Docstring의 경우 72자로 제한합니다. 제시된 길이 제한은 환경에 따라 무시해도 좋지만 파이썬 표준 정규 라이브러리의 경우 제시된 조건을 엄격히 준수합니다.


단일 연산자의 전후 중 어디서 줄바꿈을 할 것인가?

기존의 권고되는 방식은 연산자 다음에 줄바꿈을 하는 것이었으나 가독성이 떨어지는 단점이 있습니다. 다음의 예시를 참조하세요.

나쁜 예 : 연산자가 피연산자로부터 멀리 있는 경우
income = (gross_wages +
          taxable_interest +
          (dividends - qualified_dividends) -
          ira_deduction -
          student_loan_interest)
이 문제를 해결하기 위해 연산자의 앞에서 줄바꿈을 하는 것을 도날드 커누스란 컴퓨터 과학자가 권고하였습니다.
좋은 예 :
income = (gross_wages
          + taxable_interest
          + (dividends - qualified_dividends)
          - ira_deduction
          - student_loan_interest)

공백라인

최상위 함수, 클래스는 공백 라인으로 감싸서 구분합니다. 클래스 안의 메서드와 함수 내의 논리적 단위는 한줄로 구분합니다.


소스파일 인코딩

UTF-8을 기본으로 인코딩되어야 합니다. 또한 모든 식별자, 문자열 리터럴, 주석은 반드시 ASCII로 표현 가능해야 합니다. 코드의 비영문 이름을 가진 저작자를 표기할 때에는 영문으로 변환된 이름으로 적어야 합니다.


Imports

Import 섹션 분리와 순서

Import는 라인별로 분리해서 쓰는 것이 좋습니다.

좋은 예 : 
import os
import sys
나쁜 예 :  
import sys, os
허용하는 예 :
from subprocess import Popen, PIPE

최상위 함수, 클래스는 공백 라인으로 감싸서 구분합니다. 클래스 안의 메서드와 함수 내의 논리적 단위는 한줄로 구분합니다.

소스파일 인코딩
UTF-8을 기본으로 인코딩되어야 합니다. 또한 모든 식별자, 문자열 리터럴, 주석은 반드시 ASCII로 표현 가능해야 합니다. 코드의 비영문 이름을 가진 저작자를 표기할 때에는 영문으로 변환된 이름으로 적어야 합니다.

Import문은 항상 파일의 최상단에 놓이며 전역변수와 상수 전, 모듈 주석, Docstring의 후에 위치합니다. Import는 다음의 순서로 그룹지어야 합니다. 각 그룹 사이는 공백라인을 넣어 분리해야 합니다.

  1. 표준 라이브러리
  2. 3rd파티 라이브러리
  3. 로컬 라이브러리

경로 작성

패키지를 Import시 다음과 같이 절대 경로로 작성하는 것이 권고 됩니다.

import mypkg.sibling
from mypkg import sibling
from mypkg.sibling import example

다음과 같이 상대 경로로 작성할 수 있으나 표준 라이브러리를 사용할 경우, Python 3 환경일 경우 반드시 절대 경로로 작성합니다.

from . import sibling
from .sibling import example

클래스를 포함하고 있는 모듈에서 클래스를 Import하는 경우 다음과 같이 써도 좋습니다.

from myclass import MyClass
from foo.bar.yourclass import YourClass

만일 지역변수와 충돌이 일어날 경우 다음과 같이 Import해도 좋으며 "myclass.MyClass" 또는 "foo.bar.yourclass.YourClass" 로 사용하면 됩니다.

import myclassimport foo.bar.yourclass

와일드 카드를 이용한 Import 피하기

모듈의 던더(Ex. __all__, __author__, __version__) 이름 짓기
던더는 모듈의 Docstring의 후, from_future__ import문을 제외한 모든 Import문의 전에 위치해야 합니다. 파이썬은 future__ import가 항상 Docstring를 제외한 모든 코드 전에 올 수 있도록 강제합니다.

"""모듈 예시 입니다.
뭔 짓을 하겠지요.
"""
from __future__ import barry_as_FLUFL
__all__ = ['a', 'b', 'c']
__version__ = '0.1'
__author__ = 'Cardinal Biggles'
import os
import sys

문자열 인용부호

파이썬에서 ‘와 “는 같지만 문자열에 백슬래쉬를 쓰는 것을 피하기 위해 둘을 혼용할수있습니다. 둘중 하나를 고수하여 사용하되 예외 상황에서는 나머지 하나를 쓰는 것을 권고합니다. """ 의 경우 항상 “로 사용합니다.

공백문자

괄호 쌍 안에서 공백 삽입 하지 않음

좋은 예 : spam(ham[1], {eggs: 2})
나쁜 예 :  spam( ham[ 1 ], { eggs: 2 } )

쉼표와 닫는 괄호 사이 공백 삽입 하지 않음

좋은 예 : foo = (0,)
나쁜 예 :  bar = (0, )

콤마, 세미콜론, 콜런 직전의 공백 삽입 하지 않음

좋은 예 : if x == 4: print x, y; x, y = y, x
나쁜 예 :  if x == 4 : print x , y ; x , y = y , x

슬라이싱에서 콜론을 쓸 경우 같은 양의 공간을 쓰기

좋은 예 :
ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:]
ham[lower:upper], ham[lower:upper:], ham[lower::step]
ham[lower+offset : upper+offset]
ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)]
ham[lower + offset : upper + offset]
나쁜 예 :
ham[lower + offset:upper + offset]
ham[1: 9], ham[1 :9], ham[1:9 :3]
ham[lower : : upper]
ham[ : upper]

함수 호출 시 바로 오는 괄호, 인덱싱이나 슬라이싱에 바로 오는 괄호

좋은 예 : 
spam(1)
dct['key'] = lst[index]
나쁜 예 : 
spam (1)
dct ['key'] = lst [index]

변수 할당 시 필요 없는 공백

좋은 예 :
x = 1
y = 2
long_variable = 3
나쁜 예 : 
x             = 1
y             = 2
long_variable = 3

연산자 (Ex. =, +=, -=, ==, <, >, != 등)는 항상 공백으로 싸기

좋은 예 :
i = i + 1
submitted += 1
x = x*2 - 1
hypot2 = x*x + y*y연산자 (Ex. =, +=, -=, ==, <, >, != 등)는 항상 공백으로 싸기
c = (a+b) * (a-b)
나쁜 예 :
i=i+1
submitted +=1
x = x * 2 - 1은 예 : foo = (0,)
나쁜 예 :  bar = (0, )
hypot2 = x * x + y * y
c = (a + b) * (a - b)

Function annotations에서 -> 사이, 디폴트 값 지정 시 = 사이에 공백 문자 안 쓰기

좋은 예 :
def munge(input: AnyStr): ...
def munge() -> AnyStr: ...
def complex(real, imag=0.0):
return magic(r=real, i=imag)
def complex(real, imag=0.0):
    return magic(r=real, i=imag)
나쁜 예 :
def munge(input:AnyStr): ...
def munge()->PosInt: ...
def complex(real, imag = 0.0):
    return magic(r = real, i = imag)

Argument Annotation 와 = 기호가 결합 되었을 때는 = 주위를 공백문자로 감싸기

좋은 예 :
def munge(sep: AnyStr = None): ...
def munge(input: AnyStr, sep: AnyStr = None, limit=1000): ...
나쁜 예 :
def munge(input: AnyStr=None): ...
def munge(input: AnyStr, limit = 1000): ...

비교연산 구문에서 여러 문장을 한 줄에 쓰지 말것

좋은 예 :
if foo == 'blah':
    do_blah_thing()
do_one()
do_two()
do_three()
되도록 하지 말것:
if foo == 'blah': do_blah_thing()
do_one(); do_two(); do_three()
진짜 되도록 하지말 것:
if foo == 'blah': do_blah_thing()
for x in lst: total += x
while t < 10: t = delay()
진짜 ㅈㄴㅆㅂ 하지 말것:
if foo == 'blah': do_blah_thing()
else: do_non_blah_thing()
try: something()
finally: cleanup()
do_one(); do_two(); do_three(long, argument,
                             list, like, this)
if foo == 'blah': one(); two(); three()

후행 쉼표 (뒤에 붙는 쉼표)

후표를 포함하고 있는 경우 명확성을 위해 덩어리를 괄호로 묶어주면 좋습니다.

좋은 예 :
FILES = ('setup.cfg',)
별로 안 좋은 예 :
FILES = 'setup.cfg',

확장될 가능성을 염두하여 닫는 괄호와 같은 라인에 적지 않고 밸류값들을 한라인 씩 쉼표를 붙여 추가합니다.

좋은 예 :
FILES = [
    'setup.cfg',
    'tox.ini',
    ]
initialize(FILES,
           error=True,
           )
나쁜 예 :
FILES = ['setup.cfg', 'tox.ini',]
initialize(FILES, error=True,)

주석

코드가 업데이트 될 때마다 주석도 업데이트 되는 것은 중요합니다. 주석은 완전한 문장으로 쓰여져야하며 첫번째 단어는 영문법과 마찬가지로 대문자로 시작해야 합니다. 마지막 문장을 제외하고 문장끝의 마침표 뒤에 두 개의 공백 문자를 넣어야 합니다.

블록 주석

블록 주석은 코드와 동일한 수준으로 들여쓰기 되며 #문자를 이용하여 표시합니다. # 문자 뒤에 공백 문자 한 개가 위치한 다음 문장이 시작되도록 합니다.

인라인 주석

인라인 주석은 코드와 같은 줄에 쓰이는 주석으로 되도록 자제해야합니다. 인라인 주석은 적어도 두 칸 이상의 공백을 두고 쓰여져야 하며 #과 한칸의 공백과 같이 쓰입니다.

나쁜 예 : 명백한 것을 굳이 설명
x = x + 1                 # x를 증가시킨다.
좋은 예 :
x = x + 1       나쁜 예 : 명백한 것을 굳이 설명
x = x + 1                 # x를 증가시킨다.
좋은 예 :
x = x + 1                 # 경계 값을 보정합니다          # 경계 값을 보정합니다

Docstring (Doxygen 같은 것, """ 으로 시작하는 문장)

Public 모듈, 함수, 클래스들에 대해 Docstring을 꼭 쓰십시요. Private 모듈에 쓸 필요는 없지만 그래도 어떤 동작을 하는지 def 라인 다음에 남겨야 합니다.

Ex.
"""Return a foobang
Optional plotz says to frobnicate the bizbaz first.
"""

네이밍

파이썬의 네이밍 관습은 까다로운 편이라 반드시 준수할 필요는 없습니다. 그러나 새로운모듈과 3rd 파티를 포함한 여러 패키지들은 반드시 관습을 지켜야 합니다. 이미 기존의 모듈이 표준에 맞지 않고 다른 스타일 갖고 있다면 내부적 일관성을 좀더 지키셔도 됩니다.

  • 이렇게 만들지 마세요 : I(아이), l(엘), O(오) 로 만든 외자 변수 명
  • ASCII 호환성을 갖추세요.
  • 패키지와 모듈 네이밍
    • 모듈은 모두 소문자로짧게 네이밍 합니다. 언더바는 가독성을 위해 쓰일 수 있습니다. 패키지명도 소문자로 짧게 네이밍하지만 언더바는 쓰지 않습니다.
    • C/C++ 로 만든 모듈을 파이썬을 Wrapping 하여 사용하는 경우 C/C++모듈은 언더바를 사용할 수 있습니다. (Ex. _socket)
  • 클래스 명은 주로 파스칼 케이싱으로 표현합니다. 또한 인터페이스가 문서화되있고, 주로 callable 한 객체로 사용되는 함수의 경우 (말 그대로 호출 가능한 경우. 내장 함수 callable(object)로 부터 true 값이 리턴되는 객체) 또한  파스칼 케이싱 합니다.
    • 내장된 모듈의 경우 별도의 명명 규칙이 있습니다. 내장된 모듈은 Exception 명이나 내장 상수에 대해서만 파스칼 케이싱 합니다.
  • 타입 변수

최대한 짧은 파스칼로 명명합니다. (Ex. T, AnyStr, Num) _co 나 _contra 접미사를 변수의 공변성(covariance)과 반변성(contravariance)에 따라 붙이는 것이 좋습니다.

from typing import TypeVar
VT_co = TypeVar('VT_co', covariant=True)
KT_contra = TypeVar('KT_contra', contravariant=True)

공변성을 가진 객체의 예로는 파이썬의 모든 가변 컨테이너 (Ex. 튜플, Union)이가 있습니다. 반변성은 공변성과 반대되는 개념입니다.
공변성은 서브타입으로 만든 객체가 수퍼타입의 객체에 할당 가능하며 역으론 불가능한 경우를 말합니다.

예를 들어 객체 Union[Animal] (C++에서 Class<T>과 같은 부분입니다.)에는 Union[Dog]의 할당이 가능합니다.

반변성을 설명하기 위해 Animal의 run()이라는 함수가 있고, Dog의 dog_run()이라는 함수가 있다고 가정합시다.

앞선 공변성 예제에서 Dog는 Animal의 서브객체였습니다. 따라서 Animal의 run함수는 Dog의 dog_run()함수에 할당이 될 수 있습니다. 이런 경우 서브가 수퍼를 포함하고 있기 때문에 공변의 반대라는 의미로 반변이라는 표현을 씁니다.

정리하면 공변의 경우 subtype이 superType 부분집합일 때

Generic[subType] < Generic[superType] 일 경우 Generic[T]은 타입 변수 T에 대해 공변적입니다.

반대로 반변의 경우 subtype이 superType 부분집합일 때

Generic[superType] < Generic[subTypeType] 일 경우 Generic[T]은 타입 변수 T에 대해 반변적입니다.

참고 : https://blog.daftcode.pl/covariance-contravariance-and-invariance-the-ultimate-python-guide-8fabc0c24278

Exception 명명

Exception 또한 클래스이므로 클래스 명명규칙을 따릅니다. 다만 앞에 Error라는 접미사를 붙여 주세요.

전역변수 및 전역 함수

전역 변수는 되도록 모듈 ‘하나’ 안에서만 쓰일 수 있도록 합니다. from M import * _에 의해 모듈을 전부 다 로드할 땐 __all__ 이나 언더바를 붙여 전역 변수가 export되지 않도록 합니다.

참고로 __all__ 은 다음과 같은 역할을 합니다.

#foo.py
__all__ = ['bar', 'baz'] # import *에서 bar, baz를 export할 것을 명시
waz = 5
bar = 10
def baz(): return 'baz'
#temp.py
from foo import * #bar, baz가 import 됨
print bar #성공
print baz #성공
print waz # "waz"는 foo.py의 __all__에서 명시하지 않았기 때문에 exception이 발생

출처 : https://hashcode.co.kr/questions/313/python%EC%97%90%EC%84%9C-__all__%EC%9D%98-%EC%97%AD%ED%95%A0%EC%9D%80-%EB%AD%94%EA%B0%80%EC%9A%94

함수와 변수

함수와 변수명은 모두 소문자로 언더바로 단어를 나누어 작성합니다. 상황에 따라 케멀 스타일 역시 허용합니다.

함수와 메서드(클래스 안 함수) 매개변수

  • 메서드의첫 번째 인자는 무조건 self여야 합니다.
  • 클래스 메서드(@classmethod 데코레이터(@를 말함)로 표시되는 자기 자신을 첫번째 인자로 받는 메서드)의 첫 번째 인자는 무조건 cls여야 합니다
  • 예약어와 함수의 인자가 겹치는 경우 뒤에 언더바를 붙입니다.( class_)

메서드 명과 인스턴스 명

함수의 명명 규칙과 같고 public이 아닌 메서드나 인스턴스 변수의 경우 앞에 언더바를 붙입니다. 하위 클래스와 이름이 충돌할 경우는 언더바를 두 개 붙입니다. 파이썬은 이름을 가지고 맹글링 하기 때문에 예를 들어 Foo라는 객체가 __a 라는 속성을 가질 경우 Foo.__a로 접근할 수 없습니다. 따라서 언더바 2개로 구분하는 것은 이러한 충돌을 피할 목적으로만 사용하는 것이 좋습니다.

*네이밍 맹글링
컴파일러가 선언 시 사용했던 이름을 구분을 위해 컴파일 단계에서 일정한 규칙으로 바꾸는 것을 말합니다.
출처 : http://blog.naver.com/PostView.nhn?blogId=no1rogue&logNo=30095521394

상수

모두 대문자로 언더바로 단어를 구분합니다.

상속 디자인

모두 대문자로 언더바로 단어를 구분합니다.

파이썬도 private, public, protected에 해당하는 개념이 있습니다. 몇 가지 파이썬스러운 다음의 가이드를 참조합니다.

  • Public attribute(파이썬에서 메서드와 멤버변수를 이르는 말)은 앞에 언더바를 붙이지 않습니다.
  • Public attribute이 예약어 겹칠 경우 뒤에 언더스코어를 하나 붙여 구분합니다.
  • 간단한 attribute은 이름만 노출시켜 접근자나 변경자 (get/set 같은) 같이 번거로운 메서드를 통하지 않고 조작이 가능토록 하세요.
    • 연산이 많은 동작에 property를(@property, attribute의 get/set 함수 역할을 하는 것) 사용하는 것을 피하세요.
  • 서브 클래스(자식 클래스)를 만들 때 사용되길 원치 않는 attribute이 있는 경우 네이밍을 앞에 더블 언더바를 쓰고 뒤에 언더바를 붙이지 않는 방식으로 네이밍을 합니다. 파이썬의 맹글링 알고리즘에 따라 이렇게 명명된 attribute은 충돌되지 않으면서도 서브클래스가 같은 이름의 attribute을 쓰는 경우를 방지 합니다.
    • 맹글링에는 클래스 명만이 단순히 사용되므로 서브와 수퍼의 클래스 명이 같은 경우에는 충돌이 발생할 수 있습니다.
    • 맹글링 알고리즘은 문서화가 잘 되어 있으며 수동으로 수행 가능하니 불편함을 야기할 경우 직접 손볼 수 있습니다.

Public 과 내부 인터페이스

문서화 되지 않은 인터페이스는 명시되지 않는 한 내부 인터페이스로 간주합니다. Introspection을 잘 지원하기 위해 __all__ 을 이용하여 public API를 세팅하는 것이 좋습니다. 명시하지 않으면 해당 모듈은 public 접근이 가능한 API가 없는 것 입니다.

여기서 Introspection은 객체의 메타데이터(클래스, 구현된 메서드, 프로퍼티, 상속받은 클래스 등의 객체정보)를 검사하는 과정을 말합니다.

출처 : https://soulpark.wordpress.com/2012/09/03/objective_c_introspection/

__all__을 적절히 설정하였더라도 내부 인터페이스는 앞에 언더바 한개를 붙여 구분해야 합니다. 또한 인터페이스가 포함한 어떠한 네임스페이스(패키지, 모듈 또는 클래스)라도 내부적인 것으로 간주되면 인터페이스 자체도 내부적인 것으로 간주됩니다.

프로그래밍 습관

  • 파이썬 코드는 여러 다른 방식으로 작성되더라도 결점을 갖지 않아야 합니다.
    ( PyPy, Jython, IronPython, Cython, Psyco)  
    • 예를 들어CPython이 문자열 연결에서 a += b or a = a + b 같은 형식을 효율적으로 구현하는 것에 의존하지 마세요. 이러한 최적화는 CPython에서도 취약합니다. 차라리 .join을 쓰세요.
  • = 보다 >= 또는 <=로 비교하는 것이 안전합니다.
    • 또한 None, false을 다른 값으로 (예를 들면 X)로 대체하지 마세요.
  • ‘is not’연산자를 ‘not ... is’보다 선호합시다.
    • 좋은 예 :
      if foo is not None:
    • 나쁜 예 :
      if not foo is None:
  • 정렬 구현 시 비교 방법을 한가지 방법보다 6가지 방법(__eq__, __ne__, __lt__, __le__, __gt__, __ge__)을 다 구현해 놓는 것이 좋습니다.
    • total_ordering() 데코레이터는 빠진 비교 방법을 모두 제공합니다.
  • 람다식보다는 def를 선호합시다. def 키워드는 추적에 유리합니다.
    • 좋은 예 :
      def f(x): return 2*x
    • 나쁜 예 :
      f = lambda x: 2*x
  • BaseException에서 바로 상속으로 발생시키는 예외보다 Exception에서 발생시키는 것이 좋습니다. BaseException와 Exception은 거의 같은 위계를 가지고 있지만 BaseException을 바로 상속한 경우 항상 잘못된 것을 잡는데 예약이 되어있습니다.
    • 예외의 발생 지점을 잡기보다 ‘왜’ 발생했는지에 초점을 맞추어 설계하세요.
  • 예외를 명시적으로 처리하세요.
    • Python 3 에는 ‘raise’와 ‘raise X from Y’라는 구문으로 예외를 임의로 발생시킬 수 있습니다. 이때 from의 역활은 X중에서도 Y에 의해 직접적으로 발생했음을 가리킵니다.
    • 새로운 예외로 변환 시 새로운 예외에 관련된 세부 정보를 함께 전달해야 합니다. (Ex. 원본 예외 메시지 임베딩하기)
  • Python 2에서 예외를 발생시킬 때 ‘instead of the older form raise ValueError, 'message' ’ 대신 ‘raise ValueError('message')’ 형식으로 씁니다.
    • 전자의 경우 Python 3 와 호환됩니다.
  • ‘except’ 로 퉁쳐서 에러를 잡기 보다 구체적인 에러를 잡읍시다.
    • ‘except’는 SystemExit 과KeyboardInterrupt도 캐치하기 때문에 CTRL-C 가 안먹을 수 도 있습니다.
    • try:
      import platform_specific_module
      except ImportError:
      platform_specific_module = None
  • 예외에 이름을 바인딩 할 경우 Python 2.6의 구문을 이용하여 명시적으로 쓴다.
    • 아래의 구문은 Python 3 에서 지원합니다.
      try:
      process_data()
      except Exception as exc:
      raise DataProcessingFailedError(str(exc))
  • OS 예외를 처리할 때 errno 값에 따라 Python 3.3 에 평신된 Exception 계층에 따른 예외처리를 지향합니다.
  • try/except 구문에서 try에 들어가는 코드를 최소화하세요. 이것은 마스킹 버그를 방지합니다.
Ex.
좋은 예 :
try:
    value = collection[key]
except KeyError:
	return key_not_found(key)
else:
    return handle_value(value)
나쁜 예 :
try:
    # 너무 포괄적인 처리
    return handle_value(collection[key])
except KeyError:
    # handle_value()에 의한 KeyError를 또 처리함
return key_not_found(key)
  • 만일 리소스가 지역적으로만 사용될 겨우 ‘with’ 나 ‘try/catch’구문으로 사용 후 바로 해제가 가능하도록 하세요. 
  • Context managers 는 리소스 취득/해제를 수행하지 않는 경우 별도의 함수나 메서드를 통해 호출되어야 합니다.
Ex.
좋은 예 :
with conn.begin_transaction():
	do_stuff_in_transaction(conn)
나쁜 예 :
with conn:
	do_stuff_in_transaction(conn)
  • 일관성있게 반환합니다. 반환할 것이 없는 경우 ‘None’을 표시하고 모든 경우에 대해 반환할 수 있도록 합니다.
Ex.
좋은 예 :
def foo(x):
	if x >= 0:
		return math.sqrt(x)
	else:
		return None
def bar(x):
	if x < 0:
        return None
	return math.sqrt(x)
나쁜 예 :
def foo(x):
if x >= 0:
	return math.sqrt(x)
def bar(x):
	if x < 0:
		return
’return math.sqrt(x)
  • 문자열 모듈 대신 메서드 쓰기
    • 문자열 메서드가 모듈보다 빠르고 유니코드 API 같은  API를 공유합니다.
  • 접두사/접미사를 확인하려는 경우 ''.startswith() 와 ''.endswith() 문자열 슬라이싱 대신 이용하세요. 두 함수가 좀더 간결하고 에러를 덜 생성합니다.
    • 좋은 예 : if foo.startswith('bar'):
      나쁜 예 :  if foo[:3] == 'bar':
  • 직접 객체를 비교하기보다 isinstance() 를 사용하여 비교 합니다.
    • 좋은 예 : if isinstance(obj, int):
      나쁜 예 :  if type(obj) is type(1):
    • 문자열 비교시 유니코드인지도 확인하세요. Python 3에서는 오직 str만 있지만 Python 2 는 str과 unicode로 나뉘어져 있습니다.
  • 시퀀스 (문자열, 리스트, 튜플)가 빈 경우 false 임을 이용하세요.
    • 좋은 예 : if not seq: 또는 if seq:
      나쁜 예 : if len(seq): 또는 if not len(seq):
  • boolean 값을 == 으로 비교하지 마세요.
    • 좋은 예 :   if greeting:
      나쁜 예 :    if greeting == True:
      ㅈㄴ 나쁜 예 : if greeting is True:

Function Annotations

함수 주석을 다르게 사용하려는 경우 파일의 상단 근처에 다음을 넣는 것이 좋습니다. 이는 type checkers가 모든 주석을 무시하도록 합니다.

# type: ignore

type checkers 는 선택적으로 사용하는 도구로 파이썬 인터프리터는 기본적으로 type checkers에 의한 메시지 발행이나 주석에 따른 동작 변경을 해서는 안됩니다. type checkers를 무시하고픈 유저는 무시해도 됩니다.

그러나 3rd 파티 라이브러리 사용자는 type checkers 사용을 원할 수 도 있습니다. 이 경우를 위해 stub files 사용을 권장합니다. 이는 확장자가 .pyi로 type checkers에 의해 읽히는 .py에 대응되는 파일 입니다.

Variable Annotations

Variable Annotations의 코딩 스타일 권고 사항은 상기에 기술된 함수와 같습니다.
모듈 레벨 변수, 클래스와 인스턴스 변수, 지역변수의 Annotationd은 콜론 뒤에 한칸의 공백 문자를 갖고 콜론 전에 공백 문자를 가져선 안됩니다.

만일 할당이 오른편에 있는 경우, =는 정확히 양쪽에 공백 한칸을 가져야 합니다.

좋은 예 :
code: int
class Point:
    coords: Tuple[int, int]
    label: str = '<unknown>'
나쁜 예 :
code:int  # 콜론 뒤 공백 없음
code : int  # 콜론 앞 공백 있음
class Test:
    result: int=0  # =을 공백으로 감싸지 않음

Related Posts

답글 남기기

이메일 주소는 공개되지 않습니다.