English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
사용자가 사용하는 연산자에 따라 Python에서 연산자의 의미를 변경할 수 있습니다. 이 방법을 연산자 오버로드라고 합니다.
파이썬 연산자내장 클래스에 사용됩니다. 하지만 동일한 연산자가 다른 타입에 대해서는 다른 동작을 합니다. 예를 들어,+연산자는 두 숫자에 대해서는 수학적 더하기 연산을 수행하고, 두 리스트를 결합하고, 두 문자열을 연결합니다.
Python에서 이 기능은 동일한 연산자가 상황에 따라 다른 의미를 가질 수 있도록 합니다. 이를 연산자 오버로드라고 합니다.
그런 다음, 사용자 정의 클래스의 객체와 함께 사용할 때 어떻게 될까요? 아래의 클래스를 보세요. 이 클래스는 두차원 고리에서 포인트를 모델링합니다.
class Point: def __init__(self, x = 0, y = 0): self.x = x self.y = y
그래서, 코드를 실행하고 Python 셸에서 두 개의 포인트를 더하는 것을 시도해 보세요.
>>> p1 = Point(2,3) >>> p2 = Point(-1,2) >>> p1 + p2 Traceback (most recent call last): ... TypeError: unsupported operand type(s) for +: 'Point' and 'Point'
와! 이 많은 오류가 있습니다. 두 개의 Point 객체를 더하는 데 Python이 어떻게 할 수 없게 되었는지 TypeError가 발생합니다.
또한, 좋은 소식은 계산자 오버로드를 통해 Python에 이 점을 가르칠 수 있다는 것입니다. 그러나 먼저, 특수 함수에 대해 이해해야 합니다.
Python에서 __로 시작하는 클래스 함수는 특수 함수라고 합니다. 이유는 이들은 일반 함수가 아니기 때문입니다. 우리가 정의한 __init__() 함수는 이들 중 하나입니다. 새로운 객체를 생성할 때마다 이 함수가 호출됩니다. Python에는 많은 특수 함수가 있습니다.
특별한 함수를 사용하여, 클래스를 내장 함수와 호환시킬 수 있습니다.
>>> p1 = Point(2,3) >>> print(p1) <__main__.Point object at 0x00000000031F8CC0>
출력 결과는 예상보다 나빴습니다. 하지만, 클래스에서 __str__() 메서드를 정의하면, 출력 방식을 제어할 수 있습니다. 이를 클래스에 추가합니다.
class Point: def __init__(self, x = 0, y = 0): self.x = x self.y = y def __str__(self): return "({0},{1})".format(self.x,self.y)
이제 다시 print() 함수를 시도해 보겠습니다。
>>> p1 = Point(2,3) >>> print(p1) (2,3)
실제로는,内置 함수 str()나 format()를 사용할 때, 같은 메서드를 호출합니다.
>>> str(p1) 을 호출할 때2,3)을 호출할 때 >>> format(p1) 을 호출할 때2,3)을 호출할 때
따라서, 당신이 str(p1)이나 format(p1)을 호출할 때, Python은 내부에서 p1__str__()를 오버로드하면, 특별한 함수로 알려져 있습니다. 그 다음, 연산자 오버로드로 돌아가겠습니다。
을 오버로드하려면+기호를 오버로드하려면, 클래스에서 __add__() 함수를 구현해야 합니다. 권리를 가지면 동시에 중대한 책임도 맡게 됩니다. 이 함수 내에서 원하는 일을 할 수 있습니다. 하지만 좌표의 합을 반환하는 Point 객체를 반환하는 것이 현명합니다.
class Point: def __init__(self, x = 0, y = 0): self.x = x self.y = y def __str__(self): return "({0},{1})".format(self.x,self.y) def __add__(self,other): x = self.x + other.x y = self.y + other.y return Point(x,y)
이제 다시 시도해 보겠습니다。
>>> p1 = Point(2,3) >>> p2 = Point(-1,2) >>> print(p1 + p2) (1,5)
실제로는, 당신이 p1 + p2할 때, Python은 p1 __ add __(p2),즉 Point .__ add __(p1,p2)。 마찬가지로, 다른 연산자도 오버로드할 수 있습니다. 필요한 특별한 함수 목록은 다음과 같습니다。
연산자 | 표현 | 내부 |
---|---|---|
더하기(+) | p1 + p2 | p1 __ add __(p2) |
빼기(-) | p1-p2 | p1 __ sub __(p2) |
곱하기(*) | p1 * p2 | p1 __ mul __(p2) |
승幂(**) | p1 ** p2 | p1 __ pow __(p2) |
정확한 나누기(/) | p1 / p2 | p1 __ truediv __(p2) |
정수로 나누기(//) | p1 // p2 | p1 __ floordiv __(p2) |
모듈러 연산(%) | p1%p2 | p1 __ mod __(p2) |
비트 왼쪽 이동(<<) | p1 << p2 | p1 __ lshift __(p2) |
비트 오른쪽 이동(>>) | p1 >> p2 | p1 __ rshift __(p2) |
비트 이이스(and) | p1 and p2 | p1 __ and __(p2) |
비트 이이스(or) | p1 | 2 | p1 __ or __(p2) |
비트 이이스(xor) | p1 ^ p2 | p1 __ xor __(p2) |
비트 반전(~) | 〜p1 | p1 __ invert __() |
파이썬은 연산자 오버로드를 수학 연산자로 제한하지 않습니다. 비교 연산자도 오버로드할 수 있습니다.
Point 클래스에서 작은거다(<) 연산자를 구현하고 싶다면, 이렇게 할 수 있습니다. 이는 원점에서 이 점들의 크기를 비교하고 결과를 반환하기 위해 목적을 가지고 있습니다.
class Point: def __init__(self, x = 0, y = 0): self.x = x self.y = y def __str__(self): return "({0},{1})".format(self.x,self.y) def __lt__(self,other): self_mag = (self.x ** 2) + (self.y ** 2) other_mag = (other.x ** 2) + (other.y ** 2) return self_mag < other_mag
이 예제들을 파이썬 셸에서 실행해 보세요.
>>> Point(1,1) < Point(-2,-3) True >>> Point(1,1) < Point(0.5,-0.2) False >>> Point(1,1) < Point(1,1) False
또한, 다음은 다른 비교 연산자를 오버로드하기 위해 필요한 특별한 함수들을 나열합니다.
연산자 | 표현식 | 내부 |
---|---|---|
작은거다(<) | p1 <p2 | p1 __ lt __(p2) |
작은거 같다(<=) | p1 <= p2 | p1 __ le __(p2) |
같다(==) | p1 == p2 | p1 __ eq __(p2) |
불 같다(!=) | p1!= p2 | p1 __ ne __(p2) |
큰거다(>) | p1> p2 | p1 __ gt __(p2) |
큰거 같다(>=) | p1> = p2 | p1 __ ge __(p2) |