AI Store에서 AI코딩으로 만들어진 앱을 만나보세요!
지금 바로 방문하기

언더스코어 뒤에 숨은 이야기 EP09: 속성 접근 (__getattr__, __getattribute__, __setattr__, __delattr__)

카테고리

프로그래밍/소프트웨어 개발

서브카테고리

개발 툴

대상자

- Python 개발자 (중급 이상): 객체 지향 프로그래밍(OOP) 및 속성 접근 메커니즘에 대한 심화 이해가 필요한 분

- 난이도: 중급 (Python의 내부 동작 원리와 재정의 메서드 사용법 이해 필요)

핵심 요약

  • __getattribute__: 모든 속성 접근 시 호출됨. 접근 제어, 로깅, 래퍼 구현에 사용 (예: super().__getattribute__(name) 호출 필수).
  • __getattr__: 속성이 존재하지 않을 때 호출됨. 지연 로딩(Lazy Loading), 기본값 제공, 프록시 객체 구현에 유용.
  • __setattr__: 속성 할당 시 항상 호출됨. 값 검증, 변환, 로깅에 활용 (예: super().__setattr__(name, value) 호출 필수).
  • __delattr__: 속성 삭제 시 호출됨. 특정 속성 보호, 정리 로직, 감사 기록에 사용.

섹션별 세부 요약

1. 속성 접근의 기본 동작

  • Python은 속성 접근 시 다음과 같은 순서로 처리함:

- 인스턴스의 __dict__ 확인

- 클래스 및 부모 클래스 검색

- __getattr__ 호출 (속성이 없을 경우)

  • __getattribute__는 모든 속성 접근 시 무조건 호출됨 (내장 속성도 포함).

2. `__getattribute__` 예제 및 사용 사례

  • 사용 목적:

- 속성 접근 로깅

- 접근 제어 (예: 특정 속성에 대한 권한 검증)

- 동적 행동 추가 (예: 데코레이터 활용)

  • 주의사항: super().__getattribute__(name)을 반드시 호출해야 재귀 루프를 피함.

3. `__getattr__` 예제 및 사용 사례

  • 사용 목적:

- 미리 정의되지 않은 속성에 대한 기본값 제공

- 지연 로딩(Lazy Loading) (예: 필요 시에만 데이터 로드)

- 프록시/래퍼 객체 구현

  • 예시:

```python

obj = Lazy()

print(obj.anything) # "anything" 속성이 없으므로 __getattr__ 호출

```

4. `__setattr__` 예제 및 사용 사례

  • 사용 목적:

- 할당 값의 검증/변환 (예: 나이 값이 음수가 아닌지 확인)

- 변경 로그 기록

- 특정 속성에 대한 할당 제한

  • 예시:

```python

user = Strict()

user.age = 42 # __setattr__ 호출

```

5. `__delattr__` 예제 및 사용 사례

  • 사용 목적:

- 특정 속성의 삭제 금지 (예: id 속성 보호)

- 삭제 시 로그 기록/감사

- 중심화된 정리 로직 구현

  • 예시:

```python

obj = Guarded()

obj.name = "temp"

del obj.name # __delattr__ 호출

```

6. 조합 사용 예제

  • 사용 목적:

- API 래핑, 캐싱 레이어, 도메인 특정 언어(DSL) 구축

- 프레임워크 모델 검증 (예: Django의 모델 필드 검증)

  • 예시:

```python

class Magic:

def __getattr__(self, name):

print(f"'{name}' not found. Using default.")

return 42

```

결론

- __getattribute__를 재정의할 때는 반드시 super().__getattribute__(name)을 호출해야 재귀 오류를 방지.

- __getattr__는 미리 정의되지 않은 속성에만 반응하므로, 지연 로딩이나 기본값 제공에 적합.

- __setattr____delattr__은 값을 저장/삭제하는 동작을 제어할 때 유용하며, 검증/변환/로그 기능을 추가할 수 있음.

- 실제 구현 시, 모든 메서드의 super() 호출을 반드시 포함하여 Python의 내부 메커니즘을 존중해야 함.