클래스와 인스턴스의 이해
파이썬에서 객체지향 프로그래밍은 클래스와 인스턴스를 중심으로 전개된다. 클래스는 일종의 설계도이며, 이로부터 생성된 인스턴스는 실제 데이터를 담고 있는 개별 객체다. 예를 들어, Car라는 클래스를 정의하면 각각의 차량 정보는 그 클래스의 인스턴스로 표현할 수 있다.
클래스의 장점
- 다형성(Polymorphism): 서로 다른 클래스에 속한 객체라도 동일한 인터페이스로 메서드를 호출할 수 있어 코드의 유연성을 높인다.
- 캡슐화(Encapsulation): 내부 구현을 숨기고 외부에서는 필요한 메서드만을 통해 상호작용하게 함으로써 보안과 유지보수성을 향상시킨다.
- 상속(Inheritance): 기존 클래스의 특성을 재사용하면서 새로운 기능을 추가하거나 수정할 수 있어 중복 코드를 줄이고 계층적 설계가 가능하다.
클래스 정의와 초기화
클래스는 class 키워드로 시작하며, 이름은 일반적으로 파스칼 케이스(첫 글자 대문자)를 사용하는 것이 관례다. 가장 기본적인 구성 요소 중 하나는 __init__ 메서드로, 객체 생성 시 자동으로 호출되어 초기 속성을 설정한다.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person("Alice", 30)
print(p.age) # 출력: 30
여기서 self는 현재 인스턴스를 참조하는 매개변수로, 모든 인스턴스 메서드의 첫 번째 인자로 지정되어야 한다.
비공개 멤버 (Private Members)
속성이나 메서드 이름 앞에 두 개의 밑줄(__)을 붙이면 비공개로 선언되며, 외부에서 직접 접근할 수 없게 된다. 이는 정보 은닉을 위한 수단이다.
class BankAccount:
def __init__(self, balance):
self.__balance = balance # 비공개 속성
def __get_balance(self): # 비공개 메서드
return self.__balance
def show_balance(self):
return self.__get_balance()
account = BankAccount(1000)
# account.__balance # 오류 발생
print(account.show_balance()) # 정상 작동: 1000
@classmethod 데코레이터
클래스 메서드는 인스턴스가 아닌 클래스 전체에 영향을 미치는 작업을 수행할 때 사용된다. cls를 첫 번째 인자로 받으며, 클래스 자체를 가리킨다.
class MathUtils:
@classmethod
def add_ten(cls, value):
return value + 10
result = MathUtils.add_ten(5)
print(result) # 출력: 15
이 방식은 정적 데이터 처리나 팩토리 메서드 구현에 유용하다.
@property 데코레이터
속성처럼 접근할 수 있지만 내부적으로는 메서드로 동작하도록 만들어주는 기능이다. 게터, 세터, 딜리터를 정의할 수 있어 제어력을 높인다.
class Temperature:
def __init__(self, celsius):
self._celsius = celsius
@property
def celsius(self):
return self._celsius
@celsius.setter
def celsius(self, value):
if value < -273.15:
raise ValueError("절대영도 이하 온도는 불가능합니다.")
self._celsius = value
@celsius.deleter
def celsius(self):
print("온도 데이터 삭제됨")
del self._celsius
temp = Temperature(25)
temp.celsius = 30
print(temp.celsius) # 출력: 30
상속과 다중 상속
기존 클래스의 기능을 확장하기 위해 상속을 사용한다. 단일 상속뿐 아니라 여러 부모 클래스로부터 특성을 물려받는 다중 상속도 지원한다.
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
return "멍멍!"
class Bird(Animal):
def fly(self):
return "날 수 있음"
class FlyingDog(Dog, Bird): # 다중 상속
pass
pet = FlyingDog()
print(pet.speak()) # 출력: 멍멍!
print(pet.fly()) # 출력: 날 수 있음
메서드 이름이 겹칠 경우, 상속 순서(MRO: Method Resolution Order)에 따라 먼저 등장하는 클래스의 메서드가 호출된다.
특수 메서드 (매직 메서드)
파이썬은 __init__, __str__과 같은 특수 메서드를 제공하여 연산자 오버로딩이나 내장 함수와의 통합을 가능하게 한다.
__str__ vs __repr__
__str__은 사용자 친화적인 문자열을 반환하며, print()에서 사용된다. 반면 __repr__은 개발자를 위한 더 자세한 표현을 제공하고, 가능하면 객체를 재생성할 수 있는 형태여야 한다.
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __str__(self):
return f"좌표: ({self.x}, {self.y})"
def __repr__(self):
return f"Point({self.x}, {self.y})"
p = Point(1, 2)
print(p) # 출력: 좌표: (1, 2)
print(repr(p)) # 출력: Point(1, 2)
__getitem__, __setitem__, __delitem__
이 메서드들은 객체를 마치 컨테이너(예: 리스트, 딕셔너리)처럼 동작하게 만든다.
class Storage:
def __init__(self):
self._data = {}
def __getitem__(self, key):
return self._data.get(key, None)
def __setitem__(self, key, value):
self._data[key] = value
def __delitem__(self, key):
del self._data[key]
s = Storage()
s['name'] = 'John'
print(s['name']) # 출력: John
del s['name']
__del__ 소멸자
객체가 메모리에서 해제될 때 자동으로 호출되는 메서드로, 정리 작업에 사용된다.
class Logger:
def __del__(self):
print("리소스 정리 중...")
log = Logger()
del log # 출력: 리소스 정리 중...