Python에서 @classmethod와 @staticmethod의 의미 (초보자向け)
일반적으로 메서드는 객체 인스턴스에 대해 작업을 수행하도록 설계됩니다. 하지만 특정 상황에서는 클래스 자체 또는 외부 데이터에 작업을 수행하는 메서드가 필요할 수 있습니다. 이러한 경우 @classmethod
및 @staticmethod
데코레이터를 사용할 수 있습니다.
@staticmethod
@staticmethod
데코레이터는 클래스 메서드를 정의하는 데 사용됩니다. 클래스 메서드는 클래스 자체 또는 외부 데이터에 작업을 수행하며, 객체 인스턴스에 종속되지 않습니다. @staticmethod
메서드는 첫 번째 인수로 self
또는 cls
를 받지 않습니다.
예제:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
@staticmethod
def distance(p1, p2):
dx = p1.x - p2.x
dy = p1.y - p2.y
return math.sqrt(dx ** 2 + dy ** 2)
p1 = Point(1, 2)
p2 = Point(4, 5)
distance = Point.distance(p1, p2)
print(distance) # 5.0 출력
위 예제에서 distance
메서드는 두 Point
객체 간의 거리를 계산하는 정적 메서드입니다. 이 메서드는 self
또는 cls
인수를 받지 않으며 클래스 자체 또는 외부 데이터(두 Point
객체)에 작업을 수행합니다.
@classmethod
@classmethod
데코레이터는 클래스 메서드를 정의하는 데 사용됩니다. 클래스 메서드는 클래스 자체 또는 클래스 변수에 작업을 수행합니다. @classmethod
메서드는 첫 번째 인수로 cls
를 받습니다.
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
@classmethod
def from_polar(self, r, theta):
x = r * math.cos(theta)
y = r * math.sin(theta)
return Vector(x, y)
v1 = Vector(1, 2)
v2 = Vector(3, 4)
v3 = v1 + v2
print(v3) # Vector(4, 6) 출력
v4 = Vector.from_polar(5, math.pi / 4)
print(v4) # Vector(3.535534909623623, 3.535534909623623) 출력
위 예제에서 __add__
메서드는 두 Vector
객체를 더하는 인스턴스 메서드입니다. from_polar
메서드는 극 좌표 값(r, theta)을 사용하여 Vector
객체를 생성하는 클래스 메서드입니다. 이 메서드는 첫 번째 인수로 cls
를 받아 클래스 자체에 정의된 변수에 접근할 수 있습니다.
결론
@staticmethod
및 @classmethod
데코레이터는 클래스에서 인스턴스 메서드와는 다른 종류의 메서드를 정의하는 데 사용됩니다.
@staticmethod
메서드는 클래스 자체 또는 외부 데이터에 작업을 수행하며, 객체 인스턴스에 종속되지 않습니다.@classmethod
메서드는 클래스 자체 또는 클래스 변수에 작업을 수행합니다.
예제 코드: @classmethod와 @staticmethod 데코레이터 활용
@staticmethod 데코레이터 예제
코드:
import math
class Circle:
def __init__(self, radius):
self.radius = radius
@staticmethod
def calculate_area(radius):
return math.pi * radius ** 2
circle1 = Circle(3)
print(circle1.radius) # 3 출력
area = Circle.calculate_area(5)
print(area) # 78.53975657209951 출력
설명:
Circle
클래스는radius
속성을 가진 원을 나타냅니다.calculate_area
메서드는 원의 넓이를 계산하는 정적 메서드입니다. 이 메서드는self
또는cls
인수를 받지 않으며math.pi
와radius
를 사용하여 원의 넓이를 계산합니다.circle1
객체는 반지름 3인 원을 나타냅니다.Circle.calculate_area(5)
를 사용하여 반지름 5인 원의 넓이를 계산합니다.
@classmethod 데코레이터 예제
class Employee:
def __init__(self, name, salary):
self.name = name
self.salary = salary
@classmethod
def from_string(cls, employee_string):
name, salary = employee_string.split(",")
return cls(name, float(salary))
employee1 = Employee("John Doe", 50000)
print(employee1.name, employee1.salary) # John Doe 50000 출력
employee2 = Employee.from_string("Jane Doe,60000")
print(employee2.name, employee2.salary) # Jane Doe 60000 출력
Employee
클래스는name
과salary
속성을 가진 직원을 나타냅니다.from_string
메서드는 문자열을 사용하여Employee
객체를 생성하는 클래스 메서드입니다. 이 메서드는 첫 번째 인수로cls
를 받아 클래스 자체에 정의된 생성자를 호출합니다.employee1
객체는 직접 생성됩니다.Employee.from_string("Jane Doe,60000")
을 사용하여 "Jane Doe,60000" 문자열을 사용하여employee2
객체를 생성합니다.
추가 예제
위에 제시된 예제 외에도 다음과 같은 상황에서 @classmethod
및 @staticmethod
데코레이터를 활용할 수 있습니다.
- 클래스 변수에 접근:
@classmethod
메서드를 사용하여 클래스 변수에 접근하고 조작할 수 있습니다. - 팩토리 메서드 만들기:
@classmethod
메서드를 사용하여 다양한 형식의 데이터로부터 객체를 생성하는 팩토리 메서드를 만들 수 있습니다. - 유틸리티 함수 만들기:
@staticmethod
메서드를 사용하여 클래스와 관련이 없는 유틸리티 함수를 만들 수 있습니다.
Python에서 @classmethod 및 @staticmethod의 대체 방법
따라서 다음과 같은 대체 방법을 고려할 수 있습니다.
일반 함수 사용:
@staticmethod
데코레이터 대신 일반 함수를 사용할 수 있습니다. 이렇게 하면 함수가 클래스와 관련이 없음을 명확하게 표시할 수 있습니다. 하지만 함수가 어느 클래스와 관련된지 추측하기 어려울 수 있습니다.
def distance(p1, p2):
dx = p1.x - p2.x
dy = p1.y - p2.y
return math.sqrt(dx ** 2 + dy ** 2)
p1 = Point(1, 2)
p2 = Point(4, 5)
distance = distance(p1, p2)
print(distance) # 5.0 출력
클래스 변수 사용:
@classmethod
데코레이터 대신 클래스 변수를 사용할 수 있습니다. 이렇게 하면 클래스 메서드가 클래스 변수에 의존하도록 명확하게 표시할 수 있습니다. 하지만 코드가 더 복잡해질 수 있습니다.
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
@classmethod
def from_polar(cls, r, theta):
x = r * math.cos(theta)
y = r * math.sin(theta)
return Vector(x, y)
v1 = Vector(1, 2)
v2 = Vector(3, 4)
v3 = v1 + v2
print(v3) # Vector(4, 6) 출력
Vector.POLAR_TO_VECTOR_FACTOR = 1 # 클래스 변수
v4 = Vector.from_polar(5, math.pi / 4)
print(v4) # Vector(3.535534909623623, 3.535534909623623) 출력
별도의 모듈 사용:
@staticmethod
및 @classmethod
데코레이터를 사용하는 함수를 별도의 모듈에 분리할 수 있습니다. 이렇게 하면 코드를 더욱 명확하고 유지 관리하기 쉬울 수 있습니다. 하지만 모듈을 추가로 관리해야 하는 번거로움이 있습니다.
# math_utils.py
def distance(p1, p2):
dx = p1.x - p2.x
dy = p1.y - p2.y
return math.sqrt(dx ** 2 + dy ** 2)
# vector.py
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
@classmethod
def from_polar(cls, r, theta):
x = r * math.cos(theta)
y = r * math.sin(theta)
return Vector(x, y)
# main.py
from vector import Vector
from math_utils import distance
p1 = Vector(1, 2)
p2 = Vector(4, 5)
v3 = p1 + p2
print(v3) # Vector(4, 6) 출력
v4 = Vector.from_polar(5, math.pi / 4)
print(v4) # Vector(3.535534909623623, 3.535534909623623) 출력
결론:
@classmethod
및 @staticmethod
데코레이터는 유용한 도구이지만, 상황에 따라 대체 방법을 사용하는 것이 더 적합할 수 있습니다.
python oop static-methods