- 개요
Descriptor는 객체(클래스)안에서 다른 객체(클래스)를 속성으로 갖고 있는 형태를 의미한다
get, set, delete와 같은 데이터 조작 함수를 미리 정의할 수 있다는 이점을 갖고 있다
데이터를 수정하는 경우를 Data Descriptor, 데이터를 수정하지 않는 경우를 Non Data Descriptor라고 부른다
Descriptor를 사용하면 의도하는 방향으로 클래스를 생성할 수 있다
클래스를 생성하는 방법은 다음의 2가지 방법으로 이뤄진다
- property 클래스를 사용하지 않고 Descriptor 클래스를 정의하는 방식
- property 클래스를 사용하여 Descriptor 클래스를 정의하는 방식
전자의 방식을 사용하는 경우 정해진 규격에 맞춰 함수를 정의해야 하지만,
후자의 방식을 사용하면 원하는 방식으로 함수를 정의할 수 있다
1) property 클래스를 사용하지 않는 방식
class DescriptorEx1():
def __init__(self, name="Default"):
self.name = name
def __get__(self, obj, objtype):
return f'Get method called / self : {self} / obj : {obj} / objtype : {objtype} / name : {self.name}'
def __set__(self, obj, name):
print(f"Set method called")
if isinstance(name, str):
self.name = name
else:
raise TypeError('Name Should be string')
def __delete__(self, obj):
print(f"Delete method called")
self.name = None
class Sample1():
name = DescriptorEx1()
s1 = Sample1()
s1.name = "Descriptor Test1"
print(f"{s1.name}")
del s1.name
Descriptor 클래스로 사용할 DescriptorEx1 클래스를 위와 같이 정의하였다
정의한 함수는 각각 __init__ / __get__ / __set__ / __delete__ 함수이다
각 함수의 역할은 다음과 같다
- 인스턴스의 초기화
- 데이터를 read
- 데이터를 write
- 데이터를 delete
이때 property 클래스를 사용하지 않았으므로 함수의 규격과 이름을 반드시 지켜서 오버라이드해야 한다
함수들을 오버라이드함으로써 기존의 동작 방식 외에 기능을 확장할 수 있다
outer 클래스인 Sample1에서 멤버 변수 name에 Descriptor를 사용하였다
따라서 별다른 로직없이도 name을 사용하면 Descriptor에서 정의한 함수를 호출한다

코드 실행 결과는 위와 같다
s1.name을 설정하는 코드에서 __set__ 메서드가 호출되었고
s1.name을 출력하는 코드에서 __get__ 메서드가,
s1.name을 del하는 코드에서 __delete__ 메서드가 호출되었다
2) property 클래스를 사용하는 방식
property 클래스의 구성 : class property(fget=None, fset=None, fdel=None, doc=None)
property 클래스의 경우 위와 같이 구성되어 있다
property 클래스를 사용하여 Descriptor를 구현하는 경우 함수를 임의로 설정할 수 있다
class DescriptorEx2():
def __init__(self, value):
self._name = value
def getter(self):
return f'Get method called / self : {self} / name : {self._name}'
def setter(self, value):
print(f'Set method called')
if isinstance(value, str):
self._name = value
else:
raise TypeError('value should be str')
def deletter(self):
print(f'Delete method called')
self._name = None
name = property(getter, setter, deletter, 'Property class example')
s2 = DescriptorEx2('Descriptor Test2')
print(f'{s2.name}')
s2.name = "New Name"
del s2.name
print(f"{DescriptorEx2.name.__doc__}")
Descriptor 클래스로 사용할 DescriptorEx2 클래스를 위와 같이 정의하였다
1)의 방식과 같은 역할을 수행하지만 이름과 인자를 다르게 구성한 함수들을 정의하였다
중요한 부분은 Descriptor 클래스의 마지막에 property 클래스의 인스턴스를 생성해야 한다는 점이다
순서대로 getter 함수 / setter 함수 / deletter 함수 / Descriptor 클래스의 설명을 넘겨 인스턴스를 생성해야 한다

Descriptor 클래스의 인스턴스로부터 getter / setter / deletter 함수를 호출한 결과는 위와 같다
인스턴스로부터 name을 출력하면서 getter 함수를 호출하고
인스턴스의 name을 새롭게 설정하면서 setter 함수를, 인스턴스의 name을 del 하면서 deletter 함수를 호출한다
마지막에 Descriptor 클래스로부터 클래스의 설명을 가져와 출력한다
'Python > 파이썬 오픈소스 배포' 카테고리의 다른 글
| 오픈소스 배포 프로젝트 - 1) 커스텀 패키지 (1) (0) | 2025.07.14 |
|---|---|
| Descriptor (2) (0) | 2025.07.08 |
| 메타 클래스 (3) (0) | 2025.07.05 |
| 메타 클래스 (2) (0) | 2025.07.05 |
| 메타 클래스 (1) (0) | 2025.07.04 |