콘텐츠로 건너뛰기

파이썬 [] 사용 방법: 쉽고 간편하게 배우기

[

Python 클래스에서 연산자 및 함수 오버로딩

Malay Agarwal에 의해 작성됨

Python에서 str 객체에 + 또는 * 연산자를 사용한 적이 있다면 int 또는 float 객체와 비교했을 때 다른 동작을 알아차렸을 것입니다.

이것은 Python의 내장된 연산자 또는 함수가 다른 클래스의 객체에 대해 다른 동작을 보이는 것을 의미합니다. 이것은 연산자 오버로딩 또는 함수 오버로딩이라고 합니다. 이 기능을 사용하여 직접 Python 클래스를 작성하고 객체를 더 Pythonic하게 만들 수 있습니다.

다음 내용을 학습할 것입니다:

  • Python에서 연산자와 내장 함수를 처리하는 API
  • len() 및 기타 내장 함수 뒤에 숨어있는 “비밀”
  • 클래스에서 연산자 사용 가능하게 만들기
  • 클래스를 Python의 내장 함수와 호환 가능하게 만들기

Python 데이터 모델

온라인 주문을 나타내는 클래스가 있고, 이 클래스에는 카트(list)와 고객(str 또는 다른 고객을 나타내는 클래스의 인스턴스)가 포함되어 있다고 가정해보겠습니다.

이런 경우, 카트 리스트의 길이를 얻고 싶어질 수 있습니다. Python을 처음 접하는 사람이라면 클래스에 get_cart_len() 메소드를 구현하여 이 작업을 수행하려고 할 수 있습니다. 하지만 우리의 객체를 인자로 전달하면 cart 리스트의 길이를 반환하는 방식으로 내장된 len() 함수를 구성할 수 있습니다.

또 다른 경우에는 카트에 무언가를 추가하려고 할 수 있습니다. Python을 처음 접하는 사람은 append_to_cart()라는 메소드를 구현하여 항목을 받아서 카트 리스트에 추가하는 방법을 생각할 수 있습니다. 하지만 + 연산자를 그런 방식으로 구성하여 새로운 항목을 카트에 추가할 수 있습니다.

Python의 특수 메소드

특수 메소드는 이러한 특정 동작을 수행 할 수 있도록 Python 클래스에 내장된 특별한 메소드입니다. 특수 메소드는 __으로 시작하고 더블 언더스코어(double underscore)로 끝납니다. 이러한 메소드를 사용하여 객체가 수행하는 연산 및 기능을 재정의 할 수 있습니다.

간단한 예를 들어, __add__ 메소드를 사용하면 두 개의 객제를 더하는 기능을 정의할 수 있습니다. 마찬가지로, __len__ 메소드를 사용하여 객체의 길이를 반환하는 기능을 정의할 수 있습니다.

다음의 예제는 __add__ 메소드를 사용하여 두 개의 점을 더하는 기능을 정의하는 클래스입니다.

class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
sum_x = self.x + other.x
sum_y = self.y + other.y
return Point(sum_x, sum_y)

이제 이 클래스의 두 개의 객체를 생성하고 덧셈 연산을 수행해보겠습니다.

>>> point1 = Point(1, 2)
>>> point2 = Point(3, 4)
>>> result = point1 + point2
>>> print(result.x, result.y)
4 6

위의 예제에서 point1 + point2point1.__add__(point2)와 같은 의미를 가집니다. __add__ 메소드는 Point 클래스의 두 객체를 더한 결과를 반환합니다.

이와 같이 특수 메소드를 사용하여 Python 클래스의 객체를 연산자와 함께 작동하도록 구성할 수 있습니다. 이를 통해 코드를 더 간결하게하고 표현력을 높일 수 있습니다.

내장 함수 오버로딩하기

Python의 내장 함수(reserved function)들은 객체를 조작하고 조사하기 위해 사용되는 역할을 합니다. 이러한 내장 함수들은 대부분의 경우 특정 클래스의 객체에 대해 작동하지만, Python의 특수 메소드를 사용하여 다른 클래스의 객체에 대해서도 작동하게 만들 수 있습니다.

예를 들어, len() 함수는 주어진 객체의 길이를 반환합니다. 일반적으로 이 함수는 시퀀스(sequence) 또는 컨테이너(container) 객체에 사용됩니다. 사용자 정의 클래스의 객체를 사용할 때도 len() 함수를 사용하고 싶다면 해당 클래스의 __len__ 메소드를 구현하여 이 기능을 활성화 할 수 있습니다.

다음은 사용자 정의 Student 클래스의 객체에 대해 len() 함수를 사용하는 예제입니다.

class Student:
def __init__(self, name, age):
self.name = name
self.age = age
def __len__(self):
return self.age
student1 = Student("John Doe", 20)
print(len(student1)) # Output: 20

위의 예제에서 len(student1)student1.__len__()과 같은 의미를 가지며, __len__ 메소드는 Student 클래스의 객체의 age 속성을 반환합니다.

이와 같이 내장 함수를 오버로딩하여 사용자 정의 클래스의 객체에 대해 기능을 활성화 할 수 있습니다.

내장 연산자 오버로딩하기

내장 연산자를 오버로딩하면 사용자 정의 클래스의 객체에 대해 해당 연산자를 사용할 수 있습니다. 예를 들어, + 연산자를 오버로딩하여 두 개의 객체를 더하는 기능을 추가 할 수 있습니다.

Python의 특수 메소드 중 __add__ 메소드를 사용하여 + 연산자를 오버로딩 할 수 있습니다. __add__ 메소드는 두 개의 객체가 연산될 때 호출되며, 결과를 반환합니다.

다음은 __add__ 메소드를 사용하여 두 개의 Vector 객체를 더하는 예제입니다.

class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
sum_x = self.x + other.x
sum_y = self.y + other.y
return Vector(sum_x, sum_y)
vector1 = Vector(1, 2)
vector2 = Vector(3, 4)
result = vector1 + vector2
print(result.x, result.y) # Output: 4 6

위의 예제에서 vector1 + vector2vector1.__add__(vector2)와 동일한 의미를 가지며, __add__ 메소드는 Vector 클래스의 두 객체를 더한 결과를 반환합니다.

__add__ 메소드 외에도 다른 특수 메소드를 사용하여 다른 내장 연산자를 오버로딩 할 수 있습니다. 예를 들어, - 연산자의 오버로딩은 __sub__ 메소드를 사용하여 수행할 수 있습니다.

집합 연산자와 슬라이싱 연산자 오버로딩하기

Python의 집합(set) 연산자(예: [] 또는 [:])를 사용하여 사용자 정의 클래스의 객체를 조작할 수 있습니다. 이를 위해 각각 __getitem____setitem__ 메소드를 사용하여 객체의 항목을 가져오고 설정할 수 있습니다.

다음은 __getitem____setitem__ 메소드를 사용하여 Coordinates 클래스의 객체의 항목에 액세스하는 예제입니다.

class Coordinates:
def __init__(self, data):
self.data = data
def __getitem__(self, key):
return self.data[key]
def __setitem__(self, key, value):
self.data[key] = value
coordinates = Coordinates([1, 2, 3, 4, 5])
print(coordinates[2]) # Output: 3
coordinates[2] = 10
print(coordinates[2]) # Output: 10

위의 예제에서 coordinates[2]coordinates.__getitem__(2)와 동일한 의미를 가지며, __getitem__ 메소드는 Coordinates 클래스의 객체의 항목을 반환합니다. 또한 coordinates[2] = 10coordinates.__setitem__(2, 10)와 동일한 의미를 가지며, __setitem__ 메소드는 Coordinates 클래스의 객체의 항목을 설정합니다.

이와 같이 Python의 집합 및 슬라이싱 연산자를 오버로딩하여 사용자 정의 클래스의 객체를 조작 할 수 있습니다.

완전한 예제

이제 operator overloading 및 function overloading을 이해했으므로, 이를 통해 완전한 예제를 살펴보겠습니다. 다음은 사용자 정의 Fraction 클래스의 객체에 대한 연산자 및 함수 오버로딩을 보여주는 완전한 예제입니다.

class Fraction:
def __init__(self, numerator, denominator):
self.numerator = numerator
self.denominator = denominator
def __str__(self):
return f"{self.numerator}/{self.denominator}"
def __add__(self, other):
if isinstance(other, Fraction):
numerator = (self.numerator * other.denominator) + (self.denominator * other.numerator)
denominator = self.denominator * other.denominator
return Fraction(numerator, denominator)
elif isinstance(other, int):
numerator = self.numerator + (self.denominator * other)
return Fraction(numerator, self.denominator)
def __eq__(self, other):
return self.numerator * other.denominator == self.denominator * other.numerator
fraction1 = Fraction(1, 2)
fraction2 = Fraction(3, 4)
fraction3 = Fraction(5, 6)
print(fraction1 + fraction2) # Output: 10/8
print(fraction1 + 2) # Output: 5/2
print(fraction2 == fraction3) # Output: False

위의 예제에서 Fraction 클래스는 분수를 나타내기 위해 사용됩니다. 클래스에는 분자(numerator)와 분모(denominator) 속성이 포함되어 있으며, __str__ 메소드를 사용하여 분수를 문자열로 변환합니다. __add__ 메소드는 두 개의 분수를 더하거나 분수와 정수를 더할 때 호출되며, 결과를 반환합니다. __eq__ 메소드는 두 개의 분수가 동일한지를 비교하여 True 또는 False를 반환합니다.

위의 예제에서 fraction1 + fraction2fraction1.__add__(fraction2)와 동일한 의미를 가지며, fraction1 + 2fraction1.__add__(2)와 동일한 의미를 가집니다. 또한 fraction2 == fraction3fraction2.__eq__(fraction3)와 동일한 의미를 가집니다.

이와 같이 연산자 및 함수 오버로딩을 사용하여 Python 클래스의 객체를 조작할 수 있습니다.

요약 및 자료

이번 기사에서는 Python 클래스에서 연산자 및 함수 오버로딩에 대한 개념과 구현 방법을 살펴보았습니다. 내장 함수와 연산자를 오버로딩하여 사용자 정의 클래스의 객체에 기능을 추가하고 사용할 수 있습니다. 이를 통해 더 Pythonic한 코드를 작성하고 더 다양한 기능을 갖춘 객체를 만들 수 있습니다.

또한 예제 클래스와 함께 연산자 및 함수 오버로딩을 실습할 수 있는 자료를 제공했습니다.

이제 이러한 개념을 활용하여 자신의 Python 클래스를 개발하고 사용자 정의 객체를 더욱 강력하고 유연하게 만들 수 있습니다.

참고 자료