우리 b = [1,2,3]
가 노력하고 노력한다면 :b+=(4,)
반환 b = [1,2,3,4]
하지만 우리가 시도하면 b = b + (4,)
작동하지 않습니다.
b = [1,2,3]
b+=(4,) # Prints out b = [1,2,3,4]
b = b + (4,) # Gives an error saying you can't add tuples and lists
내가 예상 b+=(4,)
당신이 목록과 튜플을 추가 할 수있는 실패,하지만했다. 그래서 b = b + (4,)
같은 결과를 기대했지만 효과가 없었습니다.
답변
“왜”질문의 문제는 대개 여러 가지 다른 것을 의미 할 수 있다는 것입니다. 나는 당신이 생각할 것으로 생각되는 각각에 대답하려고 노력할 것입니다.
“왜 다른 방식으로 작동 할 수 있습니까?” 예를 들어 this 로 대답 합니다 . 기본적으로 +=
객체의 다른 메소드를 사용하려고합니다 : __iadd__
(왼쪽에서만 확인 됨) vs __add__
및 __radd__
(왼쪽에없는 경우 오른쪽에서 확인 된 “역 추가” __add__
) 에 대한 +
.
“각 버전은 정확히 무엇을합니까?” 간단히 말해서,이 list.__iadd__
방법은 list.extend
(언어 디자인으로 인해 여전히 과제가 있습니다)와 동일한 기능을 수행합니다.
이것은 또한 예를 들어
>>> a = [1,2,3]
>>> b = a
>>> a += [4] # uses the .extend logic, so it is still the same object
>>> b # therefore a and b are still the same list, and b has the `4` added
[1, 2, 3, 4]
>>> b = b + [5] # makes a new list and assigns back to b
>>> a # so now a is a separate list and does not have the `5`
[1, 2, 3, 4]
+
물론 새로운 객체를 만들지 만 다른 시퀀스에서 요소를 가져 오는 대신 다른 목록이 명시 적으로 필요합니다.
“이것이 + =에 도움이되는 이유는 무엇입니까? 더 효율적입니다.이 extend
방법은 새로운 객체를 만들 필요가 없습니다. 물론 위와 같은 놀라운 효과가 있습니다. 일반적으로 파이썬은 실제로 효율성에 관한 것이 아닙니다. 그러나 이러한 결정은 오래 전에 이루어졌습니다.
“+로리스트와 튜플을 추가하지 않는 이유는 무엇입니까?” 여기를 참조 하십시오 (감사합니다, @ splash58); 한 가지 아이디어는 (tuple + list)가 (list + tuple)과 동일한 유형을 생성해야하며 결과가 어떤 유형이어야하는지 명확하지 않습니다. 의 유형을 변경해서는 +=
안되기 때문에이 문제 a += b
가 없습니다 a
.
답변
그것들은 동등하지 않습니다 :
b += (4,)
속기 :
b.extend((4,))
다음 +
과 같이 목록 을 연결합니다.
b = b + (4,)
튜플을 목록에 연결하려고합니다.
답변
이렇게하면 :
b += (4,)
이것으로 변환됩니다 :
b.__iadd__((4,))
이 호출 후드 b.extend((4,))
, extend
반복자를 받아이이도 작동하는 이유 :
b = [1,2,3]
b += range(2) # prints [1, 2, 3, 0, 1]
그러나 이것을 할 때 :
b = b + (4,)
이것으로 변환됩니다 :
b = b.__add__((4,))
목록 객체 만 수락하십시오.
답변
공식 문서에서 가변 시퀀스 유형의 경우 두 가지 모두 :
s += t
s.extend(t)
다음과 같이 정의됩니다.
s
내용으로 확장t
다음과 같이 정의 된 것과 다릅니다.
s = s + t # not equivalent in Python!
이것은 또한 예제와 같은 튜플을 포함하여 모든 시퀀스 유형이 작동t
한다는 것을 의미 합니다 .
그러나 범위와 발전기에서도 작동합니다! 예를 들어 다음을 수행 할 수도 있습니다.
s += range(3)
답변
“증강 된”할당 연산자 +=
는 2000 년 10 월에 릴리스 된 Python 2.0에 도입되었습니다. 설계 및 근거는 PEP 203에 설명되어 있습니다. 이 운영자의 선언 된 목표 중 하나는 전체 작업 지원입니다. 쓰기
a = [1, 2, 3]
a += [4, 5, 6]
목록 업데이트 할 예정이다 a
장소를 . 이것은리스트에 대한 다른 참조 a
, 예를 들어 a
함수 인수로 수신 된 시기 가 중요합니다 .
그러나 정수 및 문자열을 포함한 많은 Python 유형은 변경할 수 없으므로 i += 1
정수 i
가 제대로 작동하지 않을 수 있으므로 작업이 항상 제대로 수행되지 는 않습니다.
요약하면, 확장 된 할당 연산자는 가능하면 제대로 작동하고 그렇지 않으면 새 객체를 생성해야했습니다. 이러한 설계 목표를 용이하게하기 x += y
위해 다음과 같이 동작하도록 표현 을 지정했습니다.
- 경우
x.__iadd__
정의,x.__iadd__(y)
평가됩니다. - 그렇지 않으면
x.__add__
is가 구현 된x.__add__(y)
것으로 평가됩니다. - 그렇지 않으면
y.__radd__
is가 구현 된y.__radd__(x)
것으로 평가됩니다. - 그렇지 않으면 오류가 발생합니다.
이 프로세스에서 얻은 첫 번째 결과 x
는 ( NotImplemented
단일 결과가 아닌 경우 다음 단계로 조회가 계속되는 경우) 에 다시 할당됩니다 .
이 프로세스를 통해 전체 수정을 지원하는 유형이 구현 될 수 __iadd__()
있습니다. 내부 수정을 지원 하지 않는 타입은 파이썬이 자동으로 대체되기 때문에 새로운 매직 메소드를 추가 할 필요가 없습니다 x = x + y
.
마지막으로 실제 할당 된 질문에 대해 살펴 보겠습니다. 왜 할당 할당 연산자를 사용하여 튜플을 목록에 추가 할 수 있습니까? 메모리에서, 이것의 역사는 대략 다음과 같았습니다 :이 list.__iadd__()
메소드는 list.extend()
파이썬 2.0에서 이미 존재하는 메소드 를 단순히 호출하기 위해 구현되었습니다 . 반복자가 Python 2.1에 도입되었을 때 list.extend()
임의의 반복자를 허용 하도록 메소드가 업데이트되었습니다. 이러한 변경의 최종 결과는 my_list += my_tuple
Python 2.1부터 작동했습니다. list.__add__()
방법은, 그러나, 오른쪽 인수로 임의의 반복자를 지원하기로되지 않았다 – 이것은 강력하게 형식화 된 언어에 대한 부적절한 것으로 간주되었다.
필자는 개인적으로 증강 연산자의 구현이 파이썬에서 너무 복잡하다고 생각합니다. 다음과 같은 놀라운 부작용이 있습니다.
t = ([42], [43])
t[0] += [44]
두 번째 줄은 상승 TypeError: 'tuple' object does not support item assignment
, 그러나 작업이 성공적으로 어쨌든 수행 – t
될 것입니다 ([42, 44], [43])
오류를 제기 라인을 실행 한 후.
답변
대부분의 사람들은 X + = Y가 X = X + Y와 동등 할 것으로 예상합니다. 실제로 Mark Lutz의 Python Pocket Reference (4th ed)는 57 페이지의 “다음 두 형식은 거의 동일합니다. X = X + Y, X + = Y “. 그러나 파이썬을 지정한 사람들은 그것들을 동등하게 만들지 않았습니다. 아마도 그것은 파이썬이 사용되는 한 좌절 된 프로그래머들에 의해 몇 시간의 디버깅 시간을 초래할 수있는 실수 였을 것입니다. X가 변경 가능한 시퀀스 유형 인 경우 X + = Y는 X = X + Y가 아닌 X.extend (Y)와 같습니다.
답변
여기 에 설명 된 것처럼 메소드를 array
구현하지 않으면 __iadd__
메소드 b+=(4,)
의 단축 b = b + (4,)
이지만 분명히 그렇지 않습니다 . array
구현 __iadd__
메소드도 마찬가지 입니다. 분명히 __iadd__
메소드 구현 은 다음과 같습니다.
def __iadd__(self, x):
self.extend(x)
그러나 위의 코드는 실제 __iadd__
메서드 구현이 아니라 입력 과 같은 extend
메서드 가 있다고 가정하고 받아 들일 수 있습니다 tupple
.