1. 다형성 개념
다형성이란 동일한 타입이 다양한 형태를 가질 수 있는 특성을 의미합니다.
예를 들어 동물이라는 개념은 사람, 원숭이, 오리 등 다양한 형태로 존재할 수 있습니다.
1.1 코드 구현 예제
from abc import ABC, abstractmethod
class LivingBeing(ABC):
@abstractmethod
def move(self):
pass
@abstractmethod
def communicate(self, identity):
print(f'{identity}가 소통 중입니다')
class Human(LivingBeing):
def move(self):
print('사람은 걷습니다')
def communicate(self, identity):
print(f'{identity}가 말하고 있습니다')
class Primate(LivingBeing):
def move(self):
print('원숭이는 트립니다')
class Waterfowl(LivingBeing):
def move(self):
print('오리는 헤엄칩니다')
1.2 다형성의 특징
동적 바인딩: 런타임 시점에 객체의 실제 타입에 따라 적절한 메서드를 연결하는 방식입니다.
동적 다형성: 상속 관계에서 동적 바인딩을 활용한 다형성입니다.
정적 다형성: 연산자 오버로딩처럼 컴파일 시점에 결정되는 다형성입니다.
from abc import ABC, abstractmethod
class Creature(ABC):
@abstractmethod
def move(self):
pass
class Human(Creature):
def move(self):
print('사람은 걷습니다')
class Primate(Creature):
def move(self):
print('원숭이는 트립니다')
class Waterfowl(Creature):
def move(self):
print('오리는 헤엄칩니다')
individual1 = Human()
individual2 = Primate()
individual3 = Waterfowl()
individual1.move()
individual2.move()
individual3.move()
def execute_movement(entity):
entity.move()
파이썬은 모든 것이 객체이기 때문에 기본적으로 다형성을 지원합니다.
# 객체 타입에 관계없이 길이를 측정
obj1.__len__()
obj2.__len__()
obj3.__len__()
# 파이썬은 통합된 인터페이스 제공
len(obj1)
len(obj2)
len(obj3)
2. 덕 타이핑
덕 타이핑(Duck Typing)은 실제 타입보다는 행동에 초점을 맞춘 프로그래밍 패러다임입니다.
"오리처럼 걷고, 오리처럼 꽥꽥거린다면 그것은 오리다"라는 철학을 따릅니다.
class TextFile:
def read(self):
pass
def write(self):
pass
class MediaFile:
def read(self):
pass
def write(self):
pass
# 두 클래스 모두 파일과 유사한 인터페이스를 가지고 있어 파일처럼 사용 가능
3. 메서드 바인딩 종류
3.1 바인딩 메서드
개념: 호출 주체에 따라 자동으로 첫 번째 파라미터로 자신을 전달하는 메서드입니다.
- 객체에 바인딩된 메서드
- 클래스에 바인딩된 메서드
3.2 인스턴스 메서드
클래스 내부에 정의된 일반적인 메서드로, 자동으로 self 파라미터를 처리합니다.
class Learner:
def __init__(self, identifier):
self.identifier = identifier
def study(self):
print(f'{self.identifier}가 학습 중입니다')
student1 = Learner(identifier='kim')
# 인스턴스를 통해 호출 - self 자동 전달
student1.study()
# 클래스를 통해 호출 - 명시적으로 인스턴스 전달 필요
student2 = Learner(identifier='lee')
Learner.study(student1)
Learner.study(student2)
3.3 클래스 메서드
@classmethod 데코레이터를 사용하며, 첫 번째 파라미터로 클래스 자체를 받습니다.
class Learner:
def __init__(self, identifier):
self.identifier = identifier
@classmethod
def get_info(cls):
print(f'현재 클래스: {cls}')
# 인스턴스 호출 - 클래스 정보 자동 전달
student1 = Learner(identifier='kim')
student1.get_info()
# 클래스 직접 호출
Learner.get_info()
3.4 정적 메서드
@staticmethod 데코레이터를 사용하며, 어떤 파라미터도 자동으로 전달되지 않습니다.
class Learner:
def __init__(self, level):
self.level = level
@staticmethod
def calculate_grade(score):
return score * 10
# 인스턴스와 클래스 모두를 통해 호출 가능
student1 = Learner(level=3)
result1 = student1.calculate_grade(85)
result2 = Learner.calculate_grade(90)
4. 리플렉션
4.1 리플렉션 메서드
hasattr(obj, name) # 속성 존재 여부 확인
getattr(obj, name[, default]) # 속성 값 가져오기
setattr(obj, name, value) # 속성 값 설정
delattr(obj, name) # 속성 삭제
4.2 hasattr 예제
class Learner:
def __init__(self, name, level):
self.name = name
self.level = level
def study(self):
print('학습 메서드')
@classmethod
def show_class(cls):
print('클래스 메서드')
@staticmethod
def utility():
print('유틸리티 메서드')
student1 = Learner(name='kim', level=2)
print(hasattr(student1, 'name')) # True
print(hasattr(student1, 'hobby')) # False
print(hasattr(student1, 'utility')) # True
4.3 getattr 예제
student1 = Learner(name='kim', level=2)
print(getattr(student1, 'name'))
print(getattr(student1, 'hobby', '없음'))
# 메서드 접근 및 실행
method_ref = getattr(student1, 'utility')
method_ref()
4.4 setattr 예제
student1 = Learner(name='kim', level=2)
print(student1.__dict__)
# 새로운 속성 추가
setattr(student1, 'interest', 'python')
print(student1.__dict__)
# 기존 속성 수정
setattr(student1, 'interest', 'java')
print(student1.__dict__)
4.5 delattr 예제
student1 = Learner(name='kim', level=2)
print(student1.__dict__)
delattr(student1, 'level')
print(student1.__dict__)
5. 매직 메서드
5.1 초기화 및 소멸
class Learner:
def __init__(self, name):
self.name = name
print('__init__ 실행됨')
def __del__(self):
print("객체 해제됨")
student1 = Learner(name='kim')
5.2 문자열 표현
class Learner:
def __init__(self, name):
self.name = name
def __str__(self):
return f'{self.name} 학생'
student1 = Learner(name='kim')
print(student1)
5.3 문서화
class Learner:
"""
학습자 정보를 관리하는 클래스
"""
def __init__(self, name):
self.name = name
print(Learner.__doc__)
5.4 속성 접근 제어
class Learner:
def __init__(self, name):
self.name = name
def __getattr__(self, key):
return f'{key} 속성이 없습니다'
def __setattr__(self, key, value):
print(f'{key}: {value} 설정됨')
def __delattr__(self, key):
print(f'{key} 속성 삭제됨')
student1 = Learner(name='kim')
print(student1.age)
student1.skill = 'coding'
del student1.name
5.5 인덱싱 연산
class Learner:
def __init__(self, name):
self.name = name
def __getitem__(self, key):
return f'{self.name}의 {key} 정보'
def __setitem__(self, key, value):
print(f'{key}: {value} 저장됨')
def __delitem__(self, key):
print(f'{key} 항목 삭제됨')
student1 = Learner(name='kim')
print(student1['성적'])
student1['나이'] = 20
del student1['성적']