파이썬 - 래퍼 클래스
래퍼 클래스 소개
안녕하세요, 미래의 파이썬 마법사 여러분! 오늘, 우리는 래퍼 클래스의 세계로 흥미로운 여정을 떠날 거예요. 프로그래밍에 새로운 사람이라도 걱정하지 마세요 – 저는 여러분을 단계별로 이 개념을 안내해 드리겠습니다. 마치 저가 수년간 가르쳐 온 수많은 학생들을 안내한 것처럼요.
아름다운 선물을 가지고 있다고 생각해 보세요. 그러나 그 선물을 더 특별하게 만들기 위해 예쁜包装纸에 싸는 것 같아요. 이것은 파이썬에서 래퍼 클래스를 사용하는 것과 정확히 같아요 – 기존의 객체를 가져와 추가 기능을 "싸는" 것이에요. 멋지죠?
래퍼 클래스란?
래퍼 클래스는 다른 클래스의 객체나 기본 데이터형을 (또는 "싸는") 클래스입니다. 이는 스마트폰에 보호 케이스를 끼는 것과 같아요 – 폰은 여전히 같은 방식으로 작동하지만, 이제 추가 기능과 보호를 가지게 됩니다.
래퍼 클래스를 왜 사용하나요?
- 기존 객체에 새로운 기능을 추가하기 위해
- 기존 메서드의 행동을 수정하기 위해
- 원본 객체에 대한 접근을 제어하기 위해
이제 실제 코드 예제를 통해 이是如何 작동하는지 살펴보겠습니다!
기본 래퍼 클래스 예제
class StringWrapper:
def __init__(self, string):
self.string = string
def get_string(self):
return self.string
def append(self, text):
self.string += text
# 래퍼 사용
wrapped_string = StringWrapper("Hello")
print(wrapped_string.get_string()) # 출력: Hello
wrapped_string.append(" World!")
print(wrapped_string.get_string()) # 출력: Hello World!
이 예제에서, 우리는 문자열을 위한 간단한 래퍼 클래스를 정의했습니다. 이를 분석해 보죠:
-
StringWrapper
라는 클래스를 정의합니다. -
__init__
메서드는 래퍼를 문자열로 초기화합니다. -
get_string()
는包装된 문자열을检索할 수 있게 합니다. -
append()
는 새로운 메서드로 기능을 추가합니다 – 문자열에 텍스트를 추가합니다.
기본 문자열에 새로운 기능(추가)를 추가했는지 볼 수 있죠? 이것이 래퍼 클래스의 힘입니다!
래퍼 클래스로 행동 수정
이제 기존 메서드의 행동을 어떻게 수정할 수 있는지 살펴보겠습니다:
class ShoutingList(list):
def __getitem__(self, index):
return super().__getitem__(index).upper()
# 래퍼 사용
normal_list = ["hello", "world", "python"]
shouting_list = ShoutingList(normal_list)
print(normal_list[0]) # 출력: hello
print(shouting_list[0]) # 출력: HELLO
이 예제에서:
- 빌트인
list
클래스에서 상속받은ShoutingList
클래스를 만듭니다. -
__getitem__
메서드를 오버라이드하여 대문자 문자열을 반환합니다. -
ShoutingList
에서 항목에 접근할 때, 자동으로 대문자로 변환됩니다.
이는 친구가 당신이 말한 것을 반복할 때 항상 외치는 것과 같아요 – 같은 내용, 다른 전달 방식!
래퍼 클래스로 접근 제어
래퍼 클래스는 원본 객체에 대한 접근을 제어하는 데도 사용할 수 있습니다. 이는 데이터 보호 또는 읽기 전용 객체를 구현하는 데 특히 유용합니다:
class ReadOnlyWrapper:
def __init__(self, data):
self._data = data
def get_data(self):
return self._data
def __setattr__(self, name, value):
if name == '_data':
super().__setattr__(name, value)
else:
raise AttributeError("이 객체는 읽기 전용입니다")
# 래퍼 사용
data = [1, 2, 3]
read_only_data = ReadOnlyWrapper(data)
print(read_only_data.get_data()) # 출력: [1, 2, 3]
read_only_data.get_data().append(4) # 이 작동합니다, 원본 목록을 수정합니다
print(read_only_data.get_data()) # 출력: [1, 2, 3, 4]
try:
read_only_data.new_attribute = "이거 추가 못해요"
except AttributeError as e:
print(e) # 출력: 이 객체는 읽기 전용입니다
이 예제에서:
- 읽기 전용으로 동작하는
ReadOnlyWrapper
클래스를 정의합니다. -
__setattr__
를 오버라이드하여 래퍼에 새로운 속성을 추가하지 못하게 합니다. - 원본 데이터는 여전히
get_data()
를 통해 수정될 수 있지만, 래퍼 자체에 새로운 속성을 추가할 수 없습니다.
이는 박물관 전시와 같아요 – 볼 수는 있지만, 만지는 수는 없어요!
래퍼 클래스의 실제 응용
래퍼 클래스는 많은 실제 세계 응용이 있습니다. 몇 가지 예를 들어보겠습니다:
- 로깅: 메서드 호출이나 속성 접근을 로그하기 위해 객체를包装합니다.
- 캐싱: 비용이高的인 작업에 대한 캐싱 계층을 구현합니다.
- 입력 검증: 데이터가 특정 기준을 충족하기 전까지 사용하지 않도록 추가 검사합니다.
- 지연 로딩: 실제로 필요할 때까지 객체 생성을 연기합니다.
이제 간단한 로깅 래퍼를 구현해 보겠습니다:
import time
class LoggingWrapper:
def __init__(self, obj):
self.wrapped_obj = obj
def __getattr__(self, name):
original_attr = getattr(self.wrapped_obj, name)
if callable(original_attr):
def wrapper(*args, **kwargs):
start_time = time.time()
result = original_attr(*args, **kwargs)
end_time = time.time()
print(f"{name} 호출, {end_time - start_time:.2f} 초 걸림")
return result
return wrapper
return original_attr
# 래퍼 사용
class SlowCalculator:
def add(self, x, y):
time.sleep(1) # 느린 작업 시뮬레이션
return x + y
calc = SlowCalculator()
logged_calc = LoggingWrapper(calc)
result = logged_calc.add(3, 4)
print(f"결과: {result}")
출력:
add 호출, 1.00 초 걸림
결과: 7
이 예제에서:
- 모든 객체를包装할 수 있는
LoggingWrapper
를 정의합니다. - 메서드 호출을 가로채고, 시간을 기록한 후, 원래 메서드를 호출합니다.
-
SlowCalculator
객체를包装하고 메서드 호출을 로깅합니다.
이는 모든 작업을 시간을 잰 후 보고해주는 개인 비서와 같아요!
결론
래퍼 클래스는 파이썬에서 객체를 확장하고, 수정하고, 유연하게 제어할 수 있는 강력한 도구입니다. 이는 오브젝트-орientoed 프로그래밍의 스위스 Army 톱니칼과 같아요 – 다양하고 매우 유용한 상황에서 사용할 수 있습니다.
기억해 주세요, 래퍼 클래스를 마스터하기의 열쇠는 연습입니다. 다양한 객체에 대해 자신의 래퍼를 만들어 보고, 기능을 어떻게 확장할 수 있는지 확인해 보세요.谁知道? 여러분이 파이썬 마스터로서의 길을 래핑하는 방식으로 가볼 수 있을지도 모릅니다!
코딩을 즐겁게, 여러분의 코드가 항상 깔끔하게包装되길 바랍니다! ??
| 메서드 | 설명 |
|--------|-------------|
| `__init__(self, obj)` | 래퍼를包装할 객체로 초기화 |
| `__getattr__(self, name)` | 래퍼에서 속성 접근을 가로채 |
| `__setattr__(self, name, value)` | 래퍼에서 속성 대입을 가로채 |
| `__getitem__(self, key)` | 항목 접근 (예: 목록류 객체)를 가로채 |
| `__setitem__(self, key, value)` | 항목 대입을 가로채 |
| `__call__(self, *args, **kwargs)` | 包装된 객체가 호출 가능하면 래퍼를 호출 가능하게 |
| `__iter__(self)` | 包装된 객체가 이터러블이면 래퍼를 이터러블하게 |
| `__len__(self)` | 래퍼의 길이를 보고 |
| `__str__(self)` | 래퍼의 문자열 표현을 사용자 정의 |
| `__repr__(self)` | 래퍼의 repr 표현을 사용자 정의 |
이 메서드들은 여러분의 래퍼 클래스가 코드의 나머지 부분과 상호작용할 때의 거의 모든 측면을 사용자 정의할 수 있게 합니다.包装된 객체의 상호작용을 세밀하게 제어할 수 있습니다.
Credits: Image by storyset