정적 메서드와 클래스 메서드
Coddy Python 여정의 Object Oriented Programming 섹션에 포함된 레슨 — 64개 중 39번째.
일반적인 인스턴스 메서드 외에도, 클래스는 서로 다른 용도로 사용되는 정적 메서드(static methods)와 클래스 메서드(class methods)를 가질 수 있습니다.
다음은 정적 메서드의 예시입니다:
class MathHelper:
@staticmethod
def add(a, b):
return a + b
@staticmethod
def is_even(number):
return number % 2 == 0정적 메서드는 self가 필요하지 않으며 일반 함수처럼 작동합니다. 클래스에서 직접 호출하세요:
result = MathHelper.add(5, 3)
print(result)
check = MathHelper.is_even(10)
print(check)다음은 클래스 메서드의 예입니다:
class Person:
count = 0 # 클래스 변수
def __init__(self, name):
self.name = name
Person.count += 1
@classmethod
def get_count(cls):
return cls.count
@classmethod
def create_anonymous(cls):
return cls("Anonymous")클래스 메서드는 클래스 자체(cls)를 첫 번째 매개변수로 받습니다:
person1 = Person("Alice")
person2 = Person("Bob")
print(Person.get_count()) # 2클래스 메서드를 대체 생성자로 사용하세요:
anonymous = Person.create_anonymous()
print(anonymous.name) # Anonymous
print(Person.get_count()) # 3한 클래스 내에서 세 가지 메서드 유형을 모두 비교해 보세요:
class Calculator:
brand = "Python Calc"
def __init__(self, owner):
self.owner = owner
# 인스턴스 메서드 - self가 필요하며, 인스턴스 데이터에 접근합니다
def show_owner(self):
return f"Owned by {self.owner}"
# 클래스 메서드 - cls가 필요하며, 클래스 데이터에 접근합니다
@classmethod
def get_brand(cls):
return cls.brand
# 정적 메서드 - 둘 다 필요하지 않으며, 단순한 유틸리티 함수입니다
@staticmethod
def multiply(x, y):
return x * ycalc = Calculator("Alice")
print(calc.show_owner()) # Alice 소유
print(Calculator.get_brand()) # Python 계산기
print(Calculator.multiply(4, 5)) # 20출력:
8
True
2
Anonymous
3
Owned by Alice
Python Calc
20인스턴스에서도 클래스 메서드와 정적 메서드를 호출할 수 있습니다:
calc = Calculator("Bob")
print(calc.get_brand()) # Python Calc
print(calc.multiply(2, 3)) # 6주요 차이점:
- 인스턴스 메서드:
self가 필요하며, 인스턴스 데이터에 접근합니다 - 클래스 메서드:
cls가 필요하며, 클래스 데이터에 접근하고, 대체 생성자를 만드는 데 유용합니다 - 정적 메서드: 둘 다 필요하지 않으며, 클래스와 관련된 단순 유틸리티 함수입니다
핵심 포인트: 클래스에 논리적으로 속하지만 클래스나 인스턴스 데이터가 필요하지 않은 유틸리티 함수에는 @staticmethod를 사용하세요. 대체 생성자나 클래스 변수 접근과 같이 클래스 자체에 접근해야 할 때는 @classmethod를 사용하세요.
챌린지
쉬움이 챌린지에서는 포괄적인 테스트 프레임워크를 활용하면서 특정 기능을 가진 Temperature 클래스를 구현하게 됩니다.
구현을 안내하는 TODO 주석에 따라 temperature.py 파일만 수정하면 됩니다. 클래스에는 다음이 포함되어야 합니다:
- 온도 기록을 추적하기 위한 클래스 변수
- 온도 변환을 위한 정적 메서드(static method)
- 기록을 추가하고 평균을 계산하기 위한 클래스 메서드(class method)
치트 시트
클래스는 인스턴스 메서드, 정적 메서드(static methods), 클래스 메서드(class methods)의 세 가지 유형의 메서드를 가질 수 있습니다.
정적 메서드는 @staticmethod 데코레이터를 사용하며, self가 필요하지 않고 일반 함수처럼 작동합니다:
class MathHelper:
@staticmethod
def add(a, b):
return a + b
# Call directly from class
result = MathHelper.add(5, 3)클래스 메서드는 @classmethod 데코레이터를 사용하며 클래스(cls)를 첫 번째 매개변수로 받습니다:
class Person:
count = 0
def __init__(self, name):
self.name = name
Person.count += 1
@classmethod
def get_count(cls):
return cls.count
@classmethod
def create_anonymous(cls):
return cls("Anonymous")
# Usage
print(Person.get_count())
anonymous = Person.create_anonymous()주요 차이점:
- 인스턴스 메서드:
self가 필요하며, 인스턴스 데이터에 접근합니다. - 클래스 메서드:
cls가 필요하며, 클래스 데이터에 접근하고 대체 생성자를 만드는 데 유용합니다. - 정적 메서드: 둘 다 필요하지 않으며, 클래스와 관련된 단순한 유틸리티 함수입니다.
클래스 메서드와 정적 메서드 모두 클래스 또는 인스턴스에서 호출할 수 있습니다:
Calculator.multiply(4, 5) # From class
calc.multiply(4, 5) # From instance직접 해보기
from temperature import Temperature
# 포괄적인 테스트를 위한 테스트 케이스 핸들러
test_case = input()
if test_case == "default_test":
# 기본 기능 테스트
Temperature.celsius_readings = []
Temperature.add_reading(25)
Temperature.add_reading(30)
Temperature.add_reading(27)
print(f"Average reading: {Temperature.average_reading()}")
print(f"22°C is {Temperature.celsius_to_fahrenheit(22)}°F")
elif test_case == "empty_readings":
# 측정값이 없을 때 average_reading 테스트
Temperature.celsius_readings = []
print(f"Average reading: {Temperature.average_reading()}")
elif test_case == "single_reading":
# 단일 측정값으로 테스트
Temperature.celsius_readings = []
Temperature.add_reading(100)
print(f"Average reading: {Temperature.average_reading()}")
elif test_case == "negative_values":
# 음수 온도 값으로 테스트
Temperature.celsius_readings = []
Temperature.add_reading(-10)
Temperature.add_reading(-20)
Temperature.add_reading(-30)
print(f"Average reading: {Temperature.average_reading()}")
print(f"-15°C is {Temperature.celsius_to_fahrenheit(-15)}°F")
elif test_case == "zero_value":
# 0°C 측정값으로 테스트
print(f"0°C is {Temperature.celsius_to_fahrenheit(0)}°F")
elif test_case == "extreme_values":
# 극한 온도 값으로 테스트
absolute_zero = -273.15 # 섭씨 기준 절대 영도
sun_surface = 5500 # 섭씨 기준 대략적인 태양 표면 온도
print(f"{absolute_zero}°C is {Temperature.celsius_to_fahrenheit(absolute_zero)}°F")
print(f"{sun_surface}°C is {Temperature.celsius_to_fahrenheit(sun_surface)}°F")
elif test_case == "reset_readings":
# 측정값 초기화 테스트
Temperature.celsius_readings = []
Temperature.add_reading(10)
Temperature.add_reading(20)
Temperature.add_reading(30)
print(f"Average reading before reset: {Temperature.average_reading()}")
Temperature.celsius_readings = []
print(f"Average reading after reset: {Temperature.average_reading()}")
elif test_case == "decimal_values":
# 소수점 값으로 테스트
Temperature.celsius_readings = []
Temperature.add_reading(36.5) # 정상 체온
Temperature.add_reading(37.2) # 미열
Temperature.add_reading(36.9) # 정상 범위 내 변화
print(f"Average reading: {Temperature.average_reading()}")
elif test_case == "many_readings":
# 많은 측정값으로 테스트
Temperature.celsius_readings = []
for i in range(1, 101):
Temperature.add_reading(i)
print(f"Average reading with 100 values: {Temperature.average_reading()}")이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.