파이썬/기초 프로그래밍

파이썬 Descriptor와 Property 비교 예제

Data Jun 2025. 9. 15. 14:25

파이썬에서는 속성 접근 제어를 위해 크게 두 가지 방법을 사용할 수 있습니다

  • Descriptor 프로토콜 (__get__, __set__, __delete__)
  • property() 내장 함수 (또는 @property 데코레이터)

이번 글에서는 두 가지 방법을 예제를 통해 비교해보겠습니다.

 

1. Descriptor 기본 예제

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('Set method called.')
        if isinstance(name, str):
            self.name = name
        else:
            raise TypeError('Name should be string.')

    def __delete__(self, obj):
        print('Delete method called')
        self.name = None


class Sample1(object):
    name = DescriptorEx1()  # 디스크립터 객체 사용

실행 예시

s1 = Sample1()

# __set__ 호출
s1.name = 'Descriptor Test1'

# __get__ 호출
print(s1.name)

# 타입 에러 발생
# s1.name = 10

실행 결과

Set method called.
Get method called. -> self:<__main__.DescriptorEx1 object at ...>, obj:<__main__.Sample1 object at ...>, objtype:<class '__main__.Sample1'>, name: Descriptor Test1

Descriptor는 클래스 단위에서 속성을 제어할 수 있으며, __get__, __set__, __delete__ 메서드를 직접 구현해야 합니다. 따라서 세밀한 제어가 가능하지만 코드가 다소 장황해질 수 있습니다.

 

2. property() 메서드 활용 예제

class DescriptorEx2:
    def __init__(self, value):
        self._name = value

    def getVal(self):
        return 'Get method called. -> self: {}, name: {}'.format(self, self._name)

    def setVal(self, value):
        print('Set method called.')
        if isinstance(value, str):
            self._name = value
        else:
            raise TypeError('Name should be string')

    def delVal(self):
        print('Delete method called.')
        self._name = None

    # property 정의
    name = property(getVal, setVal, delVal, 'Property Method Example.')

실행 예시

s2 = DescriptorEx2('Descriptor Test2.')
print(s2.name)        # getVal 호출
s2.name = 'SetVal Update!!'   # setVal 호출
del s2.name           # delVal 호출
실행 결과
Get method called. -> self: <__main__.DescriptorEx2 object at ...>, name: Descriptor Test2.
Set method called.
Delete method called.

property()를 사용하면 메서드 호출을 속성 접근처럼 쓸 수 있어 코드가 간결해집니다.
일반적으로 Pythonic한 방식으로 권장되는 방법이기도 합니다.

 

Descriptor vs Property 비교

구분 Descriptor property
선언 위치 별도의 클래스로 구현 클래스 내부 메서드와 함께 정의
제어 방식 __get__, __setl__, __delete__ 직접 구현 property() 또는 @property 데코레이터 사용
코드 가독성 다소 장황 간결
활용 범위 프레임워크, ORM, 라이브러리(세밀한 제어 필요) 일반적인 속성 캡슐화

 

 

 

정리하면

  • Descriptor는 Python의 내부 동작 원리를 이해할 때 꼭 알아야 할 개념입니다. (예: property, classmethod, staticmethod 자체도 사실 Descriptor입니다.)
  • property는 Descriptor를 간단히 활용할 수 있게 만든 편의 기능이라고 볼 수 있습니다.
  • 따라서 실무에서는 property를 주로 사용하고, 프레임워크나 라이브러리 개발 같이 깊은 제어가 필요할 때 Descriptor를 직접 구현합니다.

일반적인 속성 제어 → property 사용
프레임워크 수준의 세밀한 동작 제어 → Descriptor 직접 구현