목록으로

Python 객체 이야기

낱글, 입문
2024. 5. 7. PM 3:08:30

과자 사먹기

은행 계좌에 있는 돈으로 과자를 사먹어볼게요. 통장에 찍힌 숫자는 숫자일 뿐 과자를 사먹을 수단이 되지 못해요. 현금이든 카드든 과자를 사먹을 수 있는 수단을 이용해야 하죠. 현금을 이용해볼까요?

통장에 존재하던 숫자를 거래에 사용할 수 있는 매체인 현금으로 변환하고, 이 현금을 이용해 과자를 사먹습니다.

컴퓨터가 처리 가능한 데이터

컴퓨터에서 데이터를 다루는 것도 이와 비슷해요.

보조 기억 장치에 존재하는 파일은 통장에 찍힌 숫자와 같아요. 이 파일 자체로는 아무것도 할 수 없죠. 컴퓨터로 데이터를 다루려면 데이터를 처리하는 중앙 처리 장치(CPU)로 데이터를 보내야 하는데, CPU는 주 기억 장치에 저장된 데이터에 접근해 처리하죠. 주 기억 장치에 적재되면서 비로소 현금처럼 사용되는 거예요.

Python 객체

Python에서 모든 데이터는 객체

그렇다면 보조 기억 장치에 있는 Python 소스 파일을 주 기억 장치로 옮겨 사용하려면 어떡해야 할까요?

이 과정에 필요한 도구가 바로 Python 번역기(Interpreter)예요. Python 인터프리터는 Python 소스 파일을 읽어들여 주 기억 장치에 올라갈 수 있게 변환하고, 이 데이터를 사용자가 다루도록 합니다. 이렇게 주 기억 장치에 적재되어 사용자가 컴퓨터로 다루는 Python 데이터를 객체라고 해요.

Python에서 모든 데이터는 객체로 다뤄요. 퀴즈로 예를 살펴보죠. 다음 이미지에서 무엇이 객체로 다뤄질까요?

먼저 super_calculator() 함수가 객체가 됩니다. 함수 안에 따옴표 세 개로 묶인 문자열은 Docstring이라고 하는데, 주석이 아니라 함수 등을 설명하는 설명문으로 사용돼요. 이 데이터는 함수의 __doc__ 속성(Attribute)에 담기며, 이 역시 객체입니다. 함수의 __doc__ 속성에 할당된 문자열 객체지요.

함수가 실행되면 함수 인자인 a와 b도 객체가 됩니다. 정확히는 인자로 전달된 객체에 a와 b 이름이 붙는 거죠. 함수에 인자가 있는 경우, 함수는 객체를 전달받아 호출되면서 동작을 시작하고, 객체를 반환하면서 동작을 마쳐요.

앞서 함수도 객체라고 했지요? 그래서 함수도 다른 함수에 인자로 전달할 수 있고, 함수가 호출자에게 함수를 반환할 수도 있어요. 이런 함수를 1급(First-class) 함수라고 해요. 함수를 인자로 받아 반환하는 이런 특성을 활용하는 것이 바로 함수 장식자(decorator)지요.

수행시간측정장식자() 함수는 wrapper() 함수를 만들어 호출자에게 반환하는데, wrapper() 함수는 수행시간측정장식자() 함수가 인자로 받는 함수를 대신 호출하는데, 호출하기 직전 시간과 호출한 직후 시간의 차이를 출력하죠. 수행시간측정장식자() 함수가 바로 장식자예요.

꼭, 그리고 왜 알아야 할까?

Python에서 모든 데이터는 객체로 다룬다는 걸 꼭 알지 않아도 괜찮아요. 몰라도 Python으로 소프트웨어를 작성하는 데 문제 없죠.

그렇다면 알아야 할 이유가 있을까요? Python을 깊게 이해해 더 나은 Python 프로그램을 작성할 수 있으니까? 그런 점도 있지만, 학습 관점에서 알아야 할 이유를 들어볼게요.

과학의 한 분야인 물리학에는 여러 물리학 이론이 있어요. 다양한 물질과 물질 상호작용이 있지만, 상대성이론을 이해하면 거시 세계에서 이뤄지는 많은 것을 이해하고 설명할 수 있죠. 이런 물리 현상은 지구 뿐만 아니라, 달, 더 나아가 태양계, 더 멀리 나아가서 안드로메다 은하계에도 동일하게 작용해요. 물론 저를 비롯해 대부분 사람은 상대성이론을 깊게 이해하지 못해요. 우리 생활과 삶에 상대성이론이 미치는 영역과 상황은 무수히 많지만, 몰라도 사는 데 지장도 없죠.

Python에서 모든 데이터가 객체라는 말은, 객체의 특성을 이해하면 각양각색 데이터를 이해하고 다루는 데 유익해요. 객체의 속성과 특성이 공통되게 작용되거든요.

예를 들게요. Python에서 모든 데이터는 객체로써 object라는 객체가 시조예요. 다시 말해 모든 데이터는 object 객체가 갖고 있는 속성(Attribute)을 갖고 있죠. 이 객체에는 __doc__라는 속성이 있는데, 이 말은 Python의 모든 객체엔 __doc__ 속성이 있다는 걸 뜻해요. 그래서 Python 대화식 번역기(REPL: Read Evaluate Print Loop)에서 어떤 객체이든 help(객체)를 실행하면 그 객체의 설명문을 도움말처럼 볼 수 있어요. 우리가 만든 객체에도 __doc__에 정보를 담을 수 있고, Docstring은 객체이므로 Python 프로그램 안에서 다룰 수 있어요. 코드 편집기에서 객체의 정보(설명)를 도움말처럼 표시해 볼 수 있는 가장 기본 기능을 포함해, Docstring에 테스트 코드를 작성해 함수의 동작을 테스트할 수 있는 Doctest로도 활용하죠.

객체의 속성, 멤버와 메서드

Python의 모든 데이터는 객체라 했잖아요. 따라서 객체도 객체로 구성되어 있어요. 큰 객체에 각 객체가 속해 주어진 역할을 수행하는 거죠. 이렇게 객체를 구성해 객체를 구별하는 요소를 속성(Attribute)이라고 해요. 우리가 객체에 이름을(Name) 붙여 변수로 접근해 다루듯이, 객체의 속성에도 접근하는 방법이 있는데, 바로 마침표를 기호로 사용하는 거죠. 객체 표기 뒤에 마침표를 찍은 후 객체 속성의 이름을 쓰면 해당 객체의 속성에 접근하는 거예요. 존재하지 않는 속성에 접근하려 하면 속성 오류(AttributeError)가 발생하여 속성의 이름과 존재를 인지하게 되지요.

속성은 역할에 따라 크게 두 종류로 구분 짓는데, 하나는 멤버 변수이고 다른 하나는 메서드예요. 멤버 변수는 이름 그대로 객체의 구성원으로써 변수예요. 메서드는 객체에 소속된 함수라고 생각하면 되고요. 속성은 문법과 의미 측면에서 구분일 뿐, 결국엔 객체이므로 객체의 특성을 그대로 따라요. 함수의 인자로 함수를 전달하듯이 객체 뿐만 아니라 객체의 속성도 인자로 전달되지요.

객체를 만드는 세 가지 요소

객체는 크게 세 가지 요소로 만들어져요.

  • 유형(type)

  • 정체성(identity)

  • 값(value)

값(Value)은 객체에 담긴 데이터예요. 299792458이라는 정수는 정수 유형의 객체에 연결된 값이 299792458인 거죠. 궁극적으로 우리는 이 값이라는 데이터를 다루는데, = 기호로 값이 같은지 다른지, >< 기호로 크기 비교를 하죠.

유형(Type)은 객체가 어떻게 구성되어 있는지 결정짓는 요소로 Python에서는 class 문을 사용해 유형을 만들어요. Python에서 모든 데이터는 객체이고 객체를 만드는 유형도 데이터이므로 객체인데, 클래스(class)가 바로 유형 객체예요.

유형을 실체화하여(Instantiate) 만들어진 객체를 인스턴스 객체라고 해요. 모든 인스턴스 객체는 자기 자신을 식별하는 고유한 정보를 갖고 있는데 이 정보를 정체성(identity)라고 해요. 객체의 정체성은 is 예약어로 같은지 비교할 수 있어요. 값은 같아도 객체는 다를 수 있기 때문에 객체의 정체성은 is 예약어를 사용하는 거예요. 정체성도 데이터로 표현되는데, id() 함수를 이용해 알 수 있어요.

유형을 실체화한 것을 인스턴스 객체라고 했는데, 유형 객체는 type을 실체화해서 만든 객체예요. 그래서 모든 클래스는 한 번에 하나로만 존재하며, =가 아닌 is 예약어로 객체인 클래스를 비교하지요.

푸딩캠프 뉴스레터를 구독하면 학습과 성장, 기술에 관해 요약된 컨텐츠를 매주 편하게 받아보실 수 있습니다.