전문가를 위한 파이썬을 정리한 글입니다.
1. 파이썬 데이터 모델
- 파이썬의 최고 장점 중 하나의 일관성
- 데이터 모델은 일종의 프레임워크입니다.
프레임워크를 이용해서 코딩할 때는 프레임워크에 호출되는 메서드를 구현하는 데 많은 시간을 소비합니다.
그래서 파이썬 인터프리터는 특별 메서드를 호출해서 기본적인 객체 연산을 수행합니다.
- 특별 메서드는
__getiitem__()
처럼 언제난 앞뒤에 이중 언더바를 가지고 있습니다.
이러한 특별 메서드는 여러분이 구현한 객체가 다음과 같은 언어 구조체를 구현하고 지원하고 함께 사용할 수 있게 해줍니다.
- 반복, 컬렉션, 속정 접근, 연산자 오버로딩, 함수 및 메서드 호출, 객체 생성 및 제거, 문자열 표현 및 포맷, 블록 등 콘텍스트 관리
특별메서드의 장점
- 사용자가 표준 연산을 수행하기 위해 클래스 자체에서 구현한 임의 메서드명을 암기할 필요가 없습니다.
- 파이썬 표준 라이브러리에서 제공하는 풍부한 기능을 별도로 구현할 필요 없이 바로 사용할 수 있습니다.
- 시퀀스 객체에 대해서 슬라이싱을 자동으로 지원합니다.
len
- my_boject가 사용자 정의 클래스 객체면 파이썬은 여러분이 구현한
__len__()
객체메서드를 사용하게 됩니다.
- 그러나 list, str, bytearray 등과 같은 내장 자료형의 경우 파이썬 인터프리터는 손쉬운 방법을 선택합니다.
실제로 CPython의 경우 len() 메서드는 메모리에 있는 모든 가변 크기 내장 객체를 나타내는 PyVarObject C 구조체의 ob_size 필드의 값을 반환합니다.
이 방법이 메서드를 호출하는 방법보다 빠릅니다.
repr
__repr__()
특별 메서드는 객체를 문자열로 표현하기 위해 repr() 내장 메서드에 의해 호출됩니다.
만일 __repr__()
메서드를 구현하지 않으면 예를 들어 Vector를 구현했다고 하면 Vector 객체는 콘솔에 <Vector obejct at 0x10e10070>과 같은 형태로 출력됩니다.
- % 연산자를 사용하는 고전적인 포맷 문자열에서의 %r 플레이스홀더처럼, 또는 str.format()메서드에서 사용하는 새로운 포맷 문자열 구문의 !r 변환 필드처럼, 대화형 콘솔과 디버거는 평가된 표현식의 결과에 repr()을 호출합니다.
__repr__()
메서드가 반환한 문자열은 명확해야 하며, 가능하면 표현된 객체를 재생성하는 데 필요한 소스 코드와 일치해야 합니다.
__repr__()
과 __str__()
을 비교해보면 __str__()
메서드는 str() 생성자에 의해 호출되며 print() 함수에 의해 암묵적으로 사용됩니다.
__str__()
은 사용자에게 보여주기 적당한 형태의 문자열을 반환해야 합니다.
- 이 두 특별 메서드 중 하나만 구현해야 한다면
__repr()
메서드를 구현하세요. 그 이유는 파이썬 인터프리터는 __str__()
메서드가 구현되어 있지 않을 때의 대책으로 __repr__()
메서드를 호출하기 때문입니다.
어떤 때 %r와 %s 중 하나를 골라 써야 할까요 ?
%s 지정자는 str() 을 사용하여 객체를 변환하고 %r는 repr() 을 사용하여 객체를 변환합니다.
정수와 같은 일부 객체의 경우 동일한 결과를 생성하지만 repr() 은 (이 유형이 가능한 경우) 일반적으로 유효한 Python 구문을 반환합니다. 을 나타내는 객체를 명확하게 재생성하는 데 사용할 수 있습니다.
날짜를 사용한 예는 다음과 같습니다.
>>> import datetime
>>> d = datetime.date.today()
>>> str(d)
'2011-05-14'
>>> repr(d)
'datetime.date(2011, 5, 14)'
repr() Python 구문을 생성하지 않는 유형에는 file과 같은 외부 리소스를 가리키는 유형이 포함됩니다.
bool
- 파이썬에도 bool형은 있지만, if나 while문, 혹은 and, or, not에 대한 피연산자로서 불리언형이 필요한 곳에는 어떠한 객체라도 사용할 수 있습니다.
x가 참된 값인지 거짓된 값인지 판단하기 위해 파이썬 bool(x)를 적용하며, 이 함수는 항상 True나 False를 반환합니다.
__bool__()
이나 __len__()
을 구현하지 않은 경우, 기본적으로 사용자 정의 클래스의 객체는 참된 값이라고 간주됩니다. bool(x)는 x.__bool__()
을 호출한 결과를 이용합니다.
__bool__()
이 구현되어 있지 않으면 파이썬은 x.__len__()
을 호출하며, 이 특별메서드가 0을 반환하면 bool()은 False를, 그렇지 않으면 True를 반환합니다.
왜 len()은 메서드가 아닐까?
- CPython의 내장 객체에 대해서는 메서드를 호출하지 않고 단지 C 언어 구조체의 필드를 읽을 뿐입니다.
컬렉션에 들어 있는 항목 수를 가져오는 연산은 자주 발생하므로 str, list, memoryview 등의 다양한 기본형 객체에 대해 효율적으로 작동해야 합니다.
- 이러한 이유로 len(x)는 x가 내장형의 객체일 때 아주 빨리 실행이 되므로 메서드가 아닙니다.