Python에서 언더스코어(_)는 중요한 문법적 요소 중 하나이며, 다른 언어들에 비해 조금 특별합니다.

값을 무시하고 싶을 때

Unpacking에서 값을 무시하기 위해 사용 가능합니다.

특별한 의미의 네이밍을 위해 사용하는 경우

Java는 캡슐화(변수나 메소드에 대한 접근을 막는 것)를 지원하기 위해 private과 같은 접근 제한자를 사용합니다. 그러나 Python은 문법적으로 캡슐화를 지원하지 않으며, 암시적으로 private를 나타내기 위해 언더스코어로 시작하는 네이밍(private expression)을 사용합니다. 이는 Java와 같은 방어적 프로그래밍 언어에서 사용하는 진정한 의미의 private은 아니지만, Python의 Trust a developer라는 원칙에 의해 생긴 '책임 있는 개발자'를 지향하기 위한 문화입니다.

하나의 언더스코어로 시작하는 single leading underscored naming은 암시적으로 private을 표현하기 위해 사용합니다. 따라서 이와 같은 네이밍 룰에 의해 정의된 요소는 '외부에서 접근하지 말라'라는 권고의 의미를 지닙니다. 그러나 개발자를 믿는 문화를 기반으로 하고 있기 때문에, 이렇게 private 처리된 요소에 접근하더라도 warning 정도만 발생합니다.

두 개의 언더스코어로 시작하는 double leading underscored naming은 컨벤션이라기 보단 문법적인 요소입니다. 이는 해당 요소를 맹글링(컴파일러나 인터프리터가 요소의 이름을 그대로 사용하지 않고 변형시키는 것)하여 충돌을 방지하는 용도로 쓰입니다. 이와 같은 네이밍을 private를 구현하기 위해 사용하는 코드도 있지만, 이는 맹글링에 의해 private처럼 보여질 뿐이므로 이상적인 구현은 아닙니다.

매직 메소드

클래스에 대해 설명할 때, 생성자와 소멸자 메소드의 이름이 각각 __init____del__이었습니다. 이것도 특별한 방식의 네이밍에 속하며, 이와 같은 double leading, double trailing underscored naming 방식의 메소드를 magic method라고 부릅니다. 이러한 매직 메소드들은 Python 인터프리터에 의해 호출되는 메타 메소드(__init__ : 생성자, __del__ : 소멸자 등), 빌트인 함수에 의해 호출되는 메소드(__int__, __str__, __float__ 등)연산자 오버로딩 메소드 등을 정의할 때 사용합니다. 예를 들어, 빌트인 함수 len()의 경우 내부적으로 전달된 객체의 매직 메소드인 __len__을 호출하며, reversed()의 경우 매직 메소드 __reversed__를 호출합니다.


'Python 계열 > Python 레거시 글' 카테고리의 다른 글

[Python] 에러 처리  (0) 2018.07.04
[Python] 연산자 오버로딩  (0) 2018.07.02
[Python] 클래스의 상속  (0) 2018.06.30
[Python] 객체지향  (0) 2018.06.29
[Python] 빌트인 함수  (0) 2018.06.28

다른 객체지향 프로그래밍 언어들처럼, Python도 클래스의 상속을 지원합니다. 객체지향 프로그래밍이라는 패러다임은 현실 세계를 객체로 표현하기 위해 만들어졌으므로, 객체의 상속이라는 개념은 더 효율적으로 객체지향을 표현할 수 있도록 합니다. 예를 들어 토끼(Rabbit)와 고양이(Cat)가 동물(Animal)에 속하는 것을 상속 구조로 표현할 수 있습니다.

Animal이라는 클래스에 run 메소드를 정의했고, 메소드에 하나의 출력문을 두었습니다. 그리고 이 클래스를 상속받는 CatRabbit 클래스를 정의하였습니다. Cat 클래스는 상위 클래스가 가지고 있는 run 메소드를 재정의(오버라이딩)했고, Rabbit 클래스는 해당 메소드를 별도로 정의하지 않았습니다.

이후 Cat 클래스의 인스턴스에서 run 호출 시 해당 클래스의 오버라이딩된 run 메소드가 호출되며 'Cat catty is running'이 출력되었고, Cat 클래스만 가지고 있는 cry 메소드를 호출하며 'Cat catty is crying'이 출력되었습니다. Rabbit 클래스의 인스턴스에서 run 호출 시 상위 클래스인 Animal.run 메소드가 호출되며 'carrot is running'이 출력되었습니다.

상속은 보통 기존 클래스를 변경하지 않고 기능을 확장하기 위해 사용합니다. 상위 클래스가 라이브러리 형태로 제공되거나 수정이 허용되지 않는 상황이라면 상속을 이용해야만 할 것입니다.

'Python 계열 > Python 레거시 글' 카테고리의 다른 글

[Python] 연산자 오버로딩  (0) 2018.07.02
[Python] 언더스코어와 magic method  (0) 2018.07.01
[Python] 객체지향  (0) 2018.06.29
[Python] 빌트인 함수  (0) 2018.06.28
[Python] 값으로서의 함수와 lambda  (0) 2018.06.27

객체 지향 프로그래밍은 실제 세계의 모습을 프로그램 코드에 그대로 반영하기 위하여 만들어졌습니다. 과거에 시뮬레이션 프로그램을 구현하기 위해 현실 세계의 것들을 프로그래밍 언어로 표현할 필요가 있었고, 이를 위하여 객체지향 프로그래밍 패러다임이 등장하게 됩니다.

객체지향 프로그래밍 패러다임에서는 현실 세계의 물건들을 객체(object)로 표현하고, 객체를 만들기 위한 틀을 클래스(class)로 정의합니다. 기능과 특성의 모음을 변수와 메소드로서 클래스(class)라는 캡슐에 넣고, 클래스를 실체화(instance)하면 객체(object)를 만들 수 있는 것입니다.

사실 객체지향은 프로그래밍 입문자들이 종종 힘들어하는 장벽 중 하나입니다. '클래스가 어려워요'라는 생각은, 실제로 프로그래밍 언어의 요소로서 어려운 게 아니라 객체지향 프로그래밍 패러다임에 대한 이해가 부족하기 때문이므로 패러다임 자체에 대한 학습을 조금 더 하는 것이 좋습니다.

Python의 객체지향

Python은 객체지향을 지원하는 멀티 패러다임 언어입니다. 아래는 Python 클래스의 가장 간단한 예입니다.

아무런 기능도 갖고 있지 않고, 객체지향으로 따지면 정말 '틀'만을 가지고 있는 클래스입니다. 그러나 객체를 생성하는 기능은 가지고 있습니다.

FishBread()의 결과값을 돌려받은 fish_breadfish_bread_2가 객체입니다. 붕어빵을 의미하는 'FishBread'라는 틀(클래스)을 이용해 붕어빵 객체 두 개가 생성되었네요.

생성자와 소멸자, 필드와 메소드

생성자는 객체가 생성될 때 호출되는 메소드이며, 소멸자는 객체가 삭제될 때 호출되는 메소드입니다. 그리고 클래스 필드모든 객체가 공유하는 필드이고, 인스턴스 필드각각의 객체가 별도로 가지는 필드입니다. 생성자와 소멸자, 클래스 필드와 인스턴스 필드, 메소드를 모두 가지고 있는 클래스를 정의해 보겠습니다.

생성자는 __init__ 메소드로 정의(7번 라인)하고, 소멸자는 __del__ 메소드로 정의(17번 라인)합니다. 각각 객체가 생성(27, 28번 라인)되고, 삭제(43번 라인)될 때 호출됩니다. 인스턴스 필드는 self.[variable]처럼 접근(8, 9번 라인)하고, 클래스 필드는 [Class].[variable]처럼 접근(13번 라인)합니다.

한가지 특별한 점은 self 변수인데, 이는 객체 자신을 나타내며 Java의 this와 같습니다. Java와는 다르게 메소드에 self를 명시한다는 점이 조금 특별합니다. 객체에서 메소드 호출 시 자동으로 해당 객체가 self에 채워지며, 이는 Class level로 메소드를 호출하며 객체를 넘겨줄 수도 있다는 것(40번 라인)입니다.

어렵지만, 객체지향이라는 패러다임에 익숙해지길 바라는 수밖에 없습니다.

Python의 모든 요소는 객체

Python의 모든 요소(int, str, bytes, list, tuple과 같은 데이터 타입, 함수 등)는 객체입니다. 따라서 저마다의 인스턴스 필드와 메소드들이 존재합니다.


'Python 계열 > Python 레거시 글' 카테고리의 다른 글

[Python] 언더스코어와 magic method  (0) 2018.07.01
[Python] 클래스의 상속  (0) 2018.06.30
[Python] 빌트인 함수  (0) 2018.06.28
[Python] 값으로서의 함수와 lambda  (0) 2018.06.27
[Python] docstring  (0) 2018.06.26

+ Recent posts