본문 바로가기

Studying/Python

8. descriptor(디스크립터)

descriptor (디스크립터)란 파이썬 핵심 기능 중에 하나로,

 

__get__, __set__, 또는 __delete__ 메소드 중 한 개 이상으로 구현되어 있는 객체를 말한다. 

 

이렇게 구현된 디스크립터는 다른 객체의 속성으로 정의할 수 있으며,

 

그 속성에 대한 읽기, 쓰기, 삭제 연산을 할 때 동작에 따라 각각 구현된 메소드가 호출이 된다. 

 

즉, 일반적인 상황에서는 속성 B를 찾를 찾기 위해 A의 namespace를 일일이 조회를 한다고 할 때,

 

디스크립터를 사용하면, A.B로 조회가 가능하다는 것이다. 

 

이전에 배웠던, getter, setter를 high 레벨에서 사용한다면, 디스크립터는 보다 low 레벨에서 사용한다. 

 

이렇게 low 레벨에서 사용할 수 있다면, 원하는 타이밍에 내 의도에 맞는 로직을 사용할 수 있다. 

 

디스크립터의 종류에는 위에서 말한 메소드들을 어떻게 사용하느냐에 따라 구분할 수 있다. 

 

이 때, get 메소드만을 구현할 경우, non-data descriptor(비 데이터 디스크립터)로 쉽게 말해 '읽기전용',

 

set과 delete를 구현 할 경우, data descriptor(데이터 디스크립터) 즉 수정가능 으로 이해하면 된다. 

 

이렇게 디스크립터를 사용하면, 읽기 전용 객체를 생성할 수 있다는 장점이 있으며, 클래스를 의도하는 방향으로 설정할 수 있는 장점이 있다. 

 

그렇다면, 실제로 디스크립터를 사용하는 예를 확인해보자. 

 

YOO는 Sample1로 들어가지만, Descriptor1로 들어가 작동

위 그림처럼 보통 한개의 디스크립터를 생성하고, 다른 클래스에선 선언, 호출하는 방식이 일반적인 방법이다. 

 

위 코드를 통해 Sample1 클래스의 내부변수 name을 가져오거나(get), 수정하거나(set), 지울 떄(delete) 디스크립터1의 각각에 맞는 메소드가 알아서 사용되는 것을 확인할 수 있다.  

(단순히, Sample1 클래스 뿐만 아니라, 어떠한 클래스에서도 사용가능한 디스크립터가 된 것)

 

 

(잘 사용하진 않지만,) 위 방법과는 살짝 다르게 propert 클래스를 사용, 클래스 내부에서 직접 선언, 사용하는 방식으로 디스크립터를 직접 구현할 수도 있다. 

(여기서 property 클래스의 기본 속성값은 property(fget=None, fset=None, fdel=None, doc=None) )

 

 

property(fget=None, fset=None, fdel=None, doc=None)

 

이 방식의 가장 큰 특징이라면, 처음에 소개한 방법은 메소드 이름을 정석으로 사용해야하지만

 

이 두번째 방법처럼 커스텀을 할 때는, getVal 이나 setVal 처럼 메소드 이름을 마음대로 작성할 수 있다. 

 


 

여기서 getter, setter와 관련지어 생각할 부분이 발생한다. 

 

우리가 getter, setter를 배울 때 함께 배운 property 데코레이터에 대해 이야기해보자. 

 

파이썬에 내장된 @property의 가장 큰 문제점은 재사용성이다. 

 

즉, 데코레이트하는 메소드를 같은 클래스에 속한 여러 속성에 사용하지 못하고, 관련 없는 클래스에서도 재사용할 수 없다.

 

예를 들어보자. 

 

학생별 국어, 영어, 수학을 입력해야한다고 가정하고, 60점의 기본점수가 존재한다고 가정해보자. 

 

@property를 사용한다면, 각 과목별로, getter, setter를 개별적으로 설정해야 한다. 즉 재사용이 불가하다. 

 

이 때 바로 디스크립터를 사용하면 된다. 

 

디스크립터를 사용한 예시들을 더 살펴보자. 

 

 

이 예시는 get 메소드만을 구현한 non-data descriptor의 예시이다. 

 

현재 경로와 이전 경로에 위치한 파일 갯수를 구하는 클래스에서 디스크립터를 사용하였다. 

 

경로에 해당하는 파일 갯수를 구하는 디스크립터를 재사용하여 2개의 인스턴스만 추가 구현했다. 

 

(출력 오류 수정 예정)

logging에 대한 내용은 다음 게시물에서 살펴보기로 하고, 출력을 위한 구조를 짰다고 생각하고 넘어가자. 

 

Student 클래스의 변수 score을 디스크립터로 연결시켰고, 이는 s1, s2로 구분지어서 재사용성을 높였다.