파이썬 강좌 – NotImplementedError와 NotImplemented

  1. 프롤로그
  2. 개발 첫걸음
    1. 컴퓨터 구성요소 – 컴퓨터는 어떤 걸 할 수 있나?
    2. 개발과 관련된 용어
    3. 파이썬의 선택 – 왜 파이썬인가?
    4. 파이썬 설치 – Hello World 출력하기
    5. Visual Studio Code 의 편리한 기능
    6. REPL과 콘솔 창 – 파이썬 동작시키기
  3. 파이썬 기초
    1. 기초 입출력 – 소통하기
    2. 변수와 대입 – 기억하기
    3. 연산자 – 계산하기
    4. 조건문 – 분기를 만들기
    5. 반복문 – 비슷한 작업을 반복하기
    6. 반복문 코딩하기
    7. 변수와 리스트 – 비슷한 변수들을 묶기
    8. for, range – 리스트의 항목을 다루기
    9. 함수와 메소드의 호출 – 편리한 기능 이용하기
    10. 모듈 설치와 사용 – 유용한 기능 끌어다 쓰기
    11. 문자열 – 텍스트 다루기
  4. 파이썬 중급
    1. 함수를 직접 만들기 – 자주 쓰는 기능을 묶기
    2. 딕셔너리, 튜플, 세트 – 변수를 다양한 방법으로 묶기
    3. 클래스와 객체 – 변수를 사람으로 진화시키기
    1. 상속 – 클래스를 확장하기
    2. 정체성과 동질성 – 객체의 성질
    3. 특별 메소드와 연산자 – 파이썬의 내부 작동방식 이해하기
    4. 다양한 함수 인수 – 유연한 함수 만들기
    5. 슬라이싱 – 리스트 간편하게 접근하기
    6. 지능형 리스트(List Comprehension) – 리스트 갖고 놀기
    7. namedtuple - 데이터 묶음 손쉽게 만들기
    8. 조건 표현식 (Conditional Expression) - 간단한 분기 나타내기
    9. 코드 스타일 - 코드의 일관성 유지하기
    10. 명령문, 표현식 – 문법을 이루는 것들
    11. 본격적인 검색 해보기
  5. 파이썬 고급
    1. 일급 함수 다루기
    2. NotImplementedError와 NotImplemented
    3. 어노테이션 – 수월하게 프로그래밍하기
    1. 내장 함수 톺아보기
    2. 예외와 에러 – 예상치 못한 상황에 대응하기 (v0.1)
    3. 변수의 범위 – 이름 검색의 범위
  6. 파이썬 심화
    1. 시퀀스와 반복자 – 반복과 순회를 자유자재로 다루기
    2. 데코레이터 – 함수의 기능을 강화하기
    3. 프로퍼티
    4. 제너레이터
    5. async와 await
    6. 객체로서의 클래스 – 클래스를 동적으로 정의하기
  7. 파이썬 프로젝트 실습
    1. 원카드 게임 만들기 (1)
    2. 원카드 게임 만들기 (2)
    3. 원카드 게임 만들기 (3) (작성중)
    4. 턴제 자동 전투 게임 만들기 (작성중)
  8. 실전 (파이썬 외적인 것들)
    1. 정규표현식 – 문자열을 검색하고 치환하기 (작성중)
    2. 유니코드 – 컴퓨터에서 문자를 표기하는 방법
    3. html, css, 인터넷 – 자동화 첫 걸음 내딛기
    4. 네트워크 – 인터넷으로 통신하는 방법
    5. 문서 – 문맥을 읽어보기

각종 에러를 접하다 보면 NotImplementedNotImplement가 혼동된다는 점을 알 수 있습니다. 여기서는 간단하게 그 차이만 알아보고, 자세한 사항은 연결고리를 참조합니다. 아래 두 주제 전부 클래스와 밀접한 연관이 있기 때문에 아직 클래스에 익숙하지 않다면, 클래스를 더 연습하고 오시기를 권장드립니다.


NotImplementedError

상위 클래스를 설계할 때, 하위 클래스에서 반드시 오버라이드하여 상세하게 구현해야 하는 메소드를 명시하고자 하려면, 해당 메소드의 내용으로 raise NotImplementedError(메시지)만 넣어놓게 됩니다. 아래와 같이 BaseWheel로 객체를 만들어놓고 roll 메소드를 호출하려고 하면 에러가 뜬다는 것을 확인할 수 있습니다.

class BaseWheel:
    def roll(self):
        raise NotImplementedError("roll 메소드를 구현하여야 합니다.")

class FastWheel(BaseWheel):
    def roll(self):
        print("빠르게 굴러간다~!")

someWheel = BaseWheel()
someWheel.roll()
Traceback (most recent call last):
  File "c:/Users/tooth/Downloads/test.py", line 10, in <module>
    someWheel.roll()
  File "c:/Users/tooth/Downloads/test.py", line 3, in roll     
    raise NotImplementedError("roll 메소드를 구현하여야 합니다.")
NotImplementedError: roll 메소드를 구현하여야 합니다.

반면 FastWheel로 roll을 호출하면 아무런 문제가 없다는 것을 알 수 있습니다.

class BaseWheel:
    def roll(self):
        raise NotImplementedError("roll 메소드를 구현하여야 합니다.")

class FastWheel(BaseWheel):
    def roll(self):
        print("빠르게 굴러간다~!")

someWheel = FastWheel()
someWheel.roll()
빠르게 굴러간다~!

에러는 다양한 경우에서 다른 개발자에게 의도를 보여주기 좋습니다. 만약 베이스 클래스를 만들면서 반드시 구현해야 하는 기능(메소드)를 명확하게 하기 위해 raise NotImplementedError(...)를 활용하도록 합시다.


NotImplemented

어떤 클래스의 연산자, 특히 수치형에서 작동하는 중위 연산자에서 지원하지 않는 연산이라고 알리기 위해 NotImplemented 를 return 합니다. 

NotImplemented는 키워드이자 값입니다. 즉 None이나 True, False와 동등한 지위를 가진 녀석이란 것이죠. True가 참, False가 거짓, None이 아무 것도 없음을 나타내는 것처럼 NotImplemented는 ㅁ구현되지 않음을 나타내는 것입니다.

수치 연산에서 굳이 에러를 발생시키지 않고 특정한 값을 반환하는 이유는, 파이썬 인터프리터가 다른 가능한 연산을 찾아볼 기회를 주기 위해서입니다. 보통 에러를 발생시킨다면 try-except 문에서 에러를 핸들링해주지 않는 이상 프로그램이 곧장 뻗습니다. 뭔가가 실패했을 때 다른 방법을 찾아보기보다 아무 것도 못하고 프로그램이 종료된다면, 설계가 유연해지지 않겠지요.

작동 원리는 다음과 같습니다. 어떤 클래스에서 __add__ 메소드를 구현했는데 이 메소드 내부에서 NotImplemented를 반환한다면, 파이썬은 __radd__ 메소드를 검색해보는 시도 또한 해봅니다. 모든 시도가 NotImplemented로 끝난다면, 그제서야 파이썬은 TypeError를 발생시킵니다. 아래는 간단한 예시입니다.

class Time:
    def __init__(self, hour, minute, second):
        self.second = second
        self.minute = minute
        self.hour = hour
    
    def __add__(self, other):
        try:
            return Time(self.hour, self.minute, other + self.second)
        except TypeError:
            return NotImplemented
    
    def __repr__(self):
        return f'Time(hour={self.hour}, minute={self.minute}, second={self.second})'
    
    def __str__(self):
        return f'{self.hour:0>2}:{self.minute:0>2}:{self.second:0>2}'

class Minute:
    def __init__(self, value):
        self.value = value
    
    def __radd__(self, other):
        return Time(other.hour, other.minute + self.value, other.second)

t = Time(12, 23, 00)
print("초기 상태", t)

t += 22
print("22초 추가", t)

m = Minute(15)
t += m
print("15분 추가", t)

Time 객체인 tMinute 객체인 m이 더해지는 t+m 연산에서, Time.__add__ 메소드는 TypeError를 일으킵니다. 왜냐하면 Minuteint와 더하는 연산을 지원하지 않기 때문이지요. 그래서 그 경우에는 NotImplemented를 반환하도록 했습니다.

파이썬 인터프리터는 t+m 연산에서 NotImplemented가 결과로 나왔으니, 이제 m의 클래스인 Minute에서 __radd__ 메소드를 찾습니다. 어, 있네요! 이것마저 안된다면 에러를 발생시킬 터였지만, 다행히 무사히 작동합니다. __radd__에는 self가 연산자 오른쪽에 있는 값이고, other가 연산자 왼쪽에 있는 값입니다.

더 자세한 설명은 특별 메소드 글을 참조하세요.


연습 문제

  1. NotImplementedErrorNotImplemented의 차이를 설명하세요.

  1. 프롤로그
  2. 개발 첫걸음
    1. 컴퓨터 구성요소 – 컴퓨터는 어떤 걸 할 수 있나?
    2. 개발과 관련된 용어
    3. 파이썬의 선택 – 왜 파이썬인가?
    4. 파이썬 설치 – Hello World 출력하기
    5. Visual Studio Code 의 편리한 기능
    6. REPL과 콘솔 창 – 파이썬 동작시키기
  3. 파이썬 기초
    1. 기초 입출력 – 소통하기
    2. 변수와 대입 – 기억하기
    3. 연산자 – 계산하기
    4. 조건문 – 분기를 만들기
    5. 반복문 – 비슷한 작업을 반복하기
    6. 반복문 코딩하기
    7. 변수와 리스트 – 비슷한 변수들을 묶기
    8. for, range – 리스트의 항목을 다루기
    9. 함수와 메소드의 호출 – 편리한 기능 이용하기
    10. 모듈 설치와 사용 – 유용한 기능 끌어다 쓰기
    11. 문자열 – 텍스트 다루기
  4. 파이썬 중급
    1. 함수를 직접 만들기 – 자주 쓰는 기능을 묶기
    2. 딕셔너리, 튜플, 세트 – 변수를 다양한 방법으로 묶기
    3. 클래스와 객체 – 변수를 사람으로 진화시키기
    1. 상속 – 클래스를 확장하기
    2. 정체성과 동질성 – 객체의 성질
    3. 특별 메소드와 연산자 – 파이썬의 내부 작동방식 이해하기
    4. 다양한 함수 인수 – 유연한 함수 만들기
    5. 슬라이싱 – 리스트 간편하게 접근하기
    6. 지능형 리스트(List Comprehension) – 리스트 갖고 놀기
    7. namedtuple - 데이터 묶음 손쉽게 만들기
    8. 조건 표현식 (Conditional Expression) - 간단한 분기 나타내기
    9. 코드 스타일 - 코드의 일관성 유지하기
    10. 명령문, 표현식 – 문법을 이루는 것들
    11. 본격적인 검색 해보기
  5. 파이썬 고급
    1. 일급 함수 다루기
    2. NotImplementedError와 NotImplemented
    3. 어노테이션 – 수월하게 프로그래밍하기
    1. 내장 함수 톺아보기
    2. 예외와 에러 – 예상치 못한 상황에 대응하기 (v0.1)
    3. 변수의 범위 – 이름 검색의 범위
  6. 파이썬 심화
    1. 시퀀스와 반복자 – 반복과 순회를 자유자재로 다루기
    2. 데코레이터 – 함수의 기능을 강화하기
    3. 프로퍼티
    4. 제너레이터
    5. async와 await
    6. 객체로서의 클래스 – 클래스를 동적으로 정의하기
  7. 파이썬 프로젝트 실습
    1. 원카드 게임 만들기 (1)
    2. 원카드 게임 만들기 (2)
    3. 원카드 게임 만들기 (3) (작성중)
    4. 턴제 자동 전투 게임 만들기 (작성중)
  8. 실전 (파이썬 외적인 것들)
    1. 정규표현식 – 문자열을 검색하고 치환하기 (작성중)
    2. 유니코드 – 컴퓨터에서 문자를 표기하는 방법
    3. html, css, 인터넷 – 자동화 첫 걸음 내딛기
    4. 네트워크 – 인터넷으로 통신하는 방법
    5. 문서 – 문맥을 읽어보기

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 항목은 *(으)로 표시합니다

Scroll to top