2009-06-26 3 views
38

파이썬에서 + =를 재정의 할 수 있습니까?파이썬에서 "+ ="를 재정의 하시겠습니까? (__iadd__() 메서드)

+1

정확히 일치하는 http://stackoverflow.com/questions/728361/is-there-a-way-to-overload-in-python –

+4

네,하지만 사이트 검색을 사용하면 + = python 결과가 없습니다. "+ ="주위에 따옴표를 붙이면 결과는 나오지만 헤드 라인과 관련없는 것은 대부분 부적합한 판단입니다. 그래도 Google 검색을 통해 이것을 발견했습니다. –

답변

76

예, __iadd__ 메서드를 재정의하십시오. 예 :

def __iadd__(self, other): 
    self.number += other.number 
    return self  
+30

클래스가 변경 불가능한 객체를 나타내는 경우에는 '__iadd__'를 구현하면 안됩니다. 이 경우 단지'__add__'을 구현하면 대신'+ ='를 오버라이드하는데 사용됩니다. 예를 들어'__iadd__'를 사용하여 수행 할 수 없었던 문자열이나 정수 같은 불변 타입에'+ ='를 사용할 수 있습니다. –

+0

@ScottGriffiths,'__add__'을 구현했다면 반드시 __iadd__를 구현할 필요가 없다는 말입니까? 나는 당신이 링크 된 중복 된 질문을 읽었다. 그러나 왜 나는'__add__'을 구현하여 객체를 변형시킬 수 있는지 이해할 수 없기 때문에 혼란 스럽다. –

+0

@ScottGriffiths는 "반드시 __iadd__를 구현해야 할 필요는 없다" + = __? " –

12

__iadd__ 과부하뿐만 아니라 (자신을 돌아 기억!) × + = y는 X = X + Y처럼 작동합니다, 당신은 또한, __add__에 폴백 할 수 있습니다. (이것은 + = 연산자의 함정 중 하나입니다.)

>>> class A(object): 
... def __init__(self, x): 
...  self.x = x 
... def __add__(self, other): 
...  return A(self.x + other.x) 
>>> a = A(42) 
>>> b = A(3) 
>>> print a.x, b.x 
42 3 
>>> old_id = id(a) 
>>> a += b 
>>> print a.x 
45 
>>> print old_id == id(a) 
False 

심지어 trips up experts :

class Resource(object): 
    class_counter = 0 
    def __init__(self): 
    self.id = self.class_counter 
    self.class_counter += 1 

x = Resource() 
y = Resource() 

x.id, y.idResource.class_counter는 어떤 값을 가지고 당신이 기대합니까?

+7

두 번째 예제는 iadd 또는 + =와 아무런 관련이 없습니다. self.class_counter = self.class_counter + 1을 사용하면 동일한 결과가 발생합니다. 자원을 사용해야하는 경우 self를 사용하는 것은 범위 지정 문제 일뿐입니다. – FogleBird

+0

+ =를 사용하면 문제가 발생할 수있는 예입니다. __iadd__에 과부하가 걸린 경우 클래스의 사용자 (자신 포함)에게이 작업을 개방하고 있으며 최소한 문제가 이미 있는지를 알아야합니다. –

+2

@FogleBird :'foo + = bar'는''foo'가 참조하는 기존 객체를 변형 시키거나''foo''를 표현식'foo + bar'의 결과로 생성 된 객체에'foo'를 할당 할 수 있기 때문에 문제가됩니다. 그리고 그것은'foo'가'__iadd__' 메소드를 가지고 있는지 여부에 달려 있습니다. – Claudiu

9

위의 답변에서 올바르게 주어진 것 외에도 __iadd__을 재정의하면 x += y 작업이 __iadd__ 메서드의 끝으로 끝나지 않는다는 점을 명시 적으로 밝힐 필요가 있습니다.

대신 x = x.__iadd__(y)으로 끝납니다. 즉, 파이썬은 구현이 완료된 후 __iadd__ 구현의 반환 값을 "추가 대상"객체에 지정합니다.

즉, x += y 작업의 왼쪽을 변경하여 최종 암시 적 단계가 실패 할 수 있음을 의미합니다. 잘못이나 목적에 당신의 __iadd__ 구현 (x[1]에서 객체의 메서드)가 첫 번째 항목을 제거하는 경우,

>>> x[1] += y # x has two items

이제 (x[0] 일) : 당신이 목록에서 무언가를 추가 할 때 어떤 일이 일어날 수 있습니다 고려 목록의 처음부터 Python은 __iadd__ 메소드를 실행합니다. & 반환 값을 x[1]으로 지정하려고합니다. 어느 것이 더 이상 존재하지 않으며 (x[0] 일 때) ÌndexError이됩니다.

또는 당신의 __iadd__ 삽입 위의 예제의 x의 시작에 뭔가, 개체는 x[2]하지 x[1]에서, 그리고 않을 경우 어떤했다 지금 x[1]에서 이전 x[0]에서이 될 것이며, __iadd__의 반환 값을 할당 할 수 기도.

어떤 일이 일어나고 있는지 이해하지 못하면 버그가 수정되어 악몽이 될 수 있습니다.

관련 문제