본문 바로가기

Python

파이썬 스타일 가이드(Python Style Guide)

코드 작성할 때 참고하고자 이 글을 올립니다.

 

Naming Conventions

1. 모듈명(&패키지명)은 짧은 소문자로 구성, 가독성을 개선할 수 있다면 밑줄 사용

2. 클래스는 CapWords(CamelCase) 형식으로 작성

3. 함수명은 lower_case_with_underscores 형식으로 작성

 

Maximum Line Length

1. 모든 코드는 한 줄에 최대 79자까지 쓰는 것을 허용한다.

2. 백슬래시(backslash)를 사용해 연속되는 문장의 줄바꿈을 표현한다.

 

Should a line break before after a binary operator

연산자의 앞에서 줄바꿈을 한다.

income = (salary
          - taxable_interest
          - student_loan_interest)

Whitespace in Expression and Statements

무의미한 공백은 피하자.

 

Comments

Documentation Strings

# 함수의 docstring 예문

@classmethod
def compare(cls, _id):
    """마커의 아이디를 물체의 타입값으로 반환
    Args:
        _id (int): 마커의 아이디
    Return
        _type (str): 물체의 타입
    """
    conn = sqlite3.connect('semantic_map.db')
    curs = conn.cursor()
    sql = "select * from object where ID = :Id"
    curs.execute(sql, {"Id": _id})
    rows = curs.fetchall()
    _type = rows[0][0]
    conn.close()
    return _type
  
  
# 클래스의 docstring 예문
class DatabaseInterface():
    """데이터베이스 인터페이스 클래스.
    위 인터페이스 클래스의 기능으로는
    1) 마커의 아이디를 데이터베이스의 오브젝트 테이블에 비교하여 물체의 타입으로 치환.
    2) 데이터베이스 물체 정보 삽입, 수정 그리고 삭제.
    3) 원하는 물체 정보가 데이터베이스에 있는지 없는지 판별.
    4) 원하는 물체 정보를 데이터베이스에서 불러오기.

    데이터베이스 구조 :
    Type | Number | Location | Commonsense | Label | Weight
    Type: 물체의 타입 ex) apple
    Number: 해당 물체의 인덱스 ex) apple1, apple2
    Location: 해당 물체의 위치
    Commonsense: 해당물체의 상식
    Label: 상식에 대한 라벨 ex) AtLocation, RelatedTo, UsedFor
    Weight: 해당 commonsense에 대한 가중치(ConceptNet5 기준)
    """
Attributes:
    module_level_variable1 (int): Module level variables
    module_level_variable2 (int): Module level variables
"""

module_level_variable1 = 12345
module_level_variable2 = 98765

 

클래스에 대하여

  • 클래스 변수: 클래스 정의에서 메서드 밖에 존재하는 변수를 클래스 변수(class variable)라고 한다. 해당 클래스를 사용하는 모두에게 공용으로 사용되는 변수이다. 클래스 내외부에서 "클래스명.변수명" 또는 클래스 내부 클래스 메서드에서 "cls.변수명"으로 엑세스할 수 있다
  • 인스턴스 변수: 각 개게 인스턴스마다 별도로 존재한다. 클래스 내부에서는 "self.변수"를 사용하여 엑세스하고, 클래스 밖에서는 "객체변수.인스턴스변수"와 같이 엑세스 한다.
  • Python 클래스는 기본적으로 모든 멤버가 public 이라고 할 수 있다.
    • 접근성에 관련된 문제이다.
    • Python 코딩 관례(convention)상 내부적으로만 사용하는 변수 혹은 메서드는 그 이름 앞에 하나의 밑줄(_)을 붙인다. 하지만 실제로는 외부에서 접근 가능하다. 만약 특정 변수명이나 메서드를 private으로 만들어야 한다면 두 개의 밑줄(__)을 변수 혹은 메서드 앞에 붙이면 된다.
def __init__(self, width, height):
    self.width = width
    self.height = height
    
    #private 변수 __area
    self.__area = width * height
    
# prvate 메서드
def __internal_run(self):
    pass

 

  • 정적 메서드와 클래스 메서드
    • 정적 메서드는 self 파라미터를 갖지 않고 인스턴스 변수에 엑세스할 수 없다. 보통 객체 필드와는 독립적이지만 로직상 클래스내에 포함되는 메서드에 사용된다.
    • 클래스 메서드는 객체 인스턴스를 의미하는 "self." 대신 "cls."라는 클래스를 의미하는 파라미터를 전달받아 클래스 변수에 엑세스할 수 있다.
    • 일반적으로는 인스턴스 데이터를 엑세스 할 필요가 없는 경우 클래스 메서드나 정적 메서드를 사용하는데, 이 때 보통 클래스 변수를 엑세스할 필요가 있을 때는 클래스 메서드를, 이를 엑세스할 필요가 없을 때는 정적 메서드를 사용한다.
    • 클래스 변수를 엑세스할 때는 클래스명을 사용하는 것이 좋다.
class Rectangle:
    count = 0 # 클래스 변수
    
    def __init__(self, width, height):
        self.width = width
        self.height = height
        Rectangle.count +=1 # 클래스 변수 접근
        
    # 인스턴스 메서드
    def calcArea(self):
        area = self.width * self.height
        return area
    
    # 정적 메서드
    @staticmethod
    def isSquare(rectWidth, rectHeight):
        return rectWidth == rectHeight
    
    # 클래스 메서드
    @classmethod
    def printCount(cls):
        print(cls.count)
        
# 테스트
square = Rectangle.isSquare(5, 5)
print(square)
--> True
rect1 = Rectangle(5, 5)
rect2 = Rectangle(2, 5)
rect1.printCount()
--> 2