Python/파이썬 오픈소스 배포

Descriptor (2)

monstro 2025. 7. 8. 12:12
728x90
반응형

- 개요

DescriptorProperty의 차이점은 다음과 같다

  • Descriptor : get / set과 같은 데이터 조작 함수의 기능을 확장
  • Property : 어노테이션등을 통한 데이터 조작 함수의 정의

 

따라서 단순한 기능을 제공하는 Property와 다르게 Descriptor를 사용하면 많은 장점을 얻을 수 있다

  • 1) 상황에 맞는 메서드 구현을 통한 OOP 구현
  • 2) Property와는 다르게 재사용이 가능
  • 3) ORM Framework(객체-관계 매핑) 사용

 

1) Descriptor 사용 예제 (1)

class DirectoryFileCount:
    def __get__(self, obj, objtype=None):
        print(os.listdir((obj.dirname)))
        return len(os.listdir(obj.dirname))

class DirectoryPath:
    # Descriptor Instance
    size = DirectoryFileCount()

    def __init__(self, dirname):
        self.dirname = dirname

# 현재 경로
s = DirectoryPath('./')
s.size

# 이전 경로
g = DirectoryPath('../')
g.size

 

DirectoryFileCount와 DirectoryPath로 구성된 총 2개의 클래스를 생성하였다

 

우선, DirectoryFileCount 클래스 Descriptor로서 동작한다

property 클래스를 사용하지 않아 __get__ 함수의 규격을 유지하여 함수를 오버라이드하였다

인자로 받은 오브젝트의 dirname 속성을 사용하여

해당 속성이 존재하는 디렉토리의 모든 파일을 출력하고 개수를 반환한다

 

DirectoryPath 클래스Descriptor 클래스의 인스턴스size라는 이름의 속성으로 사용한다

__init__ 함수에서 dirname을 인자로 받아 속성으로 사용한다

 

 

코드의 실행 결과는 위와 같다

현재 경로를 dirname 속성으로 사용하여 DirectoryPath 클래스의 인스턴스를 정의하고

해당 인스턴스에서 size를 호출하여 Descriptor의 __get__ 함수를 호출하였다

 

다음으로 이전 경로를 dirname 속성으로 사용하여 DirectoryPath 클래스의 인스턴스를 정의하고

해당 인스턴스에서 size를 호출하여 Descriptor의 __get__ 함수를 호출하였다

 

2) Descriptor 사용 예제 (2)

import logging

logging.basicConfig(
    format='%(asctime)s %(message)s',
    level=logging.INFO,
    datefmt='%Y-%m-%d %H:%M:%S'
)

class LoggedScoreAccess:

    def __init__(self, value=60):
        self.value = value

    def __get__(self, obj, objtype=None):
        logging.info('Accessing %r giving %r', 'score', self.value)
        return self.value

    def __set__(self, obj, value):
        logging.info('Updating %r to %r', 'score', self.value)
        self.value = value

class Student:
    # Descriptor instance
    score = LoggedScoreAccess()

    def __init__(self, name):
        # Regular instance attribute
        self.name = name
        
s1 = Student('Kim')

print(s1.score)
s1.score += 10
print(s1.score)

 

logging 모듈을 import하여 로그 메세지에 현재 날짜 시:분:초가 포함되도록 설정한다

 

1)의 예제와 동일하게 LoggedScoreAccess 클래스와 Student 클래스의 총 2개의 클래스로 구성되어 있다

LoggedScoreAccess 클래스 Descriptor서 property 클래스를 상속받지 않아

함수의 규격을 유지하면서 오버라이드해야 한다

  • __init__ 함수 : value 속성을 설정
  • __get__ 함수 : 로그를 찍고 value 속성의 값을 반환
  • __set__ 함수 : 로그를 찍고 value 속성의 값을 설정

 

Student 클래스에서는 Descriptor의 인스턴스를 score라는 속성으로 사용한다

score 말고도 name이라는 멤버 변수를 속성으로 사용한다

__init__ 함수에서는 name을 인자로 받아 설정한다

 

 

코드의 실행 결과는 위와 같다

처음 s1의 score를 출력하면서 __get__ 함수가 호출되고,

+= 연산자를 사용하여 값을 10 증가시키면서 __get__ 함수__set__ 함수가 호출되고,

마지막으로 s1의 score를 출력하면서 다시 __get__ 함수가 호출된다

728x90
반응형