파이썬 표현식 i += x는 i = i + x와 동일합니까? 대답이 '예'라면 축하합니다. 50% 맞습니다. 왜 절반만 맞다고 하시나요? 우리의 일반적인 이해에 따르면 정수 연산과 관련하여 둘 사이에는 유사점이나 차이점이 없지만 목록 연산에서도 동일합니까? 먼저 다음 두 코드를 살펴보세요.
Code 1
>>> l1 = range(3) >>> l2 = l1 >>> l2 += [3] >>> l1 [0, 1, 2, 3] >>> l2 [0, 1, 2, 3]
Code 2
>>> l1 = range(3) >>> l2 = l1 >>> l2 = l2 + [3] >>> l1 [0, 1, 2] >>> l2 [0, 1, 2, 3]
코드 1과 코드 2의 l2 값은 동일하지만 l1의 값이 다르다는 것은 i + = x와 i = i + x가 동일하지 않다는 것을 의미합니다. 그렇다면 어떤 상황에서 동일하며, 어떤 상황에서 동일하지 않습니까?
이 문제를 명확히 하기 전에 먼저 가변 객체와 불변 객체라는 두 가지 개념을 이해해야 합니다.
Python의 모든 객체에는 고유 식별자, 유형, 값이라는 세 가지 공통 속성이 있습니다.
고유 식별: 메모리에서 객체의 고유성을 식별하는 데 사용됩니다. 객체가 생성된 후에는 변경되지 않습니다. id() 함수는 객체의 고유 식별을 볼 수 있습니다. 유형: 결정됨 객체가 지원하는 작업은 다릅니다. 예를 들어 목록에는 길이 속성이 있을 수 있지만 정수는 그렇지 않습니다. 마찬가지로, 객체의 유형이 결정되면 변경되지 않습니다. type() 함수는 객체의 유형 정보를 반환할 수 있습니다.
객체의 값은 고유 식별자와 다릅니다. 모든 객체 값이 변경 불가능한 것은 아닙니다. 일부 객체의 값은 특정 작업을 통해 변경될 수 있습니다. 변경 가능한 객체(mutable), 값을 변경할 수 없는 객체를 불변 객체(immutable)라고 합니다.
불변 객체(immutable)
불변 객체의 경우 값은 항상 , 이 개체에 대한 작업을 수행하면 새 개체가 생성됩니다.
>>> a = 1 >>> id(a) 32574568 >>> a += 1 >>> id(a) 32574544
정수 "1"은 불변 객체입니다. 처음에 a는 정수 객체 1을 가리키지만, 변수 a에 += 연산을 수행한 후에는 다른 정수 객체 2를 가리키지만, 객체 1에는 아직 아무것도 변경되지 않았으며 변수 a는 이미 새 객체 2를 가리킵니다. 일반적인 불변 객체에는 int, tuple, set, str이 포함됩니다.
변경 가능한 객체(mutable)
변경 가능한 객체의 값은 목록 객체와 같은 특정 작업을 통해 동적으로 변경될 수 있습니다. 추가 방법을 통해 변경됨 목록에 요소가 지속적으로 추가되고 목록의 값이 지속적으로 변경됩니다. 변수 개체가 두 개의 변수에 할당되면 동일한 인스턴스 개체를 공유하고 모든 메모리 주소를 가리킵니다. 변수 중 하나이며 다른 변수에도 영향을 미칩니다.
>>> x = range(3) >>> y = x >>> id(x) 139726103041232 >>> id(y) 139726103041232 >>> x.append(3) >>> x [0, 1, 2, 3] >>> y [0, 1, 2, 3] >>> id(x) 139726103041232 >>> id(y) 139726103041232
+= 작업은 먼저 객체의 __iadd__ 메서드를 호출하려고 시도합니다. 그런 메서드가 없으면 __add__ 메서드를 호출해 보겠습니다.
__add__와 __iadd__의 차이점은 무엇입니까?
__add__ 메서드는 두 개의 매개변수를 받고 그 합계를 반환합니다. 두 매개변수의 값은 변경되지 않습니다.
__iadd__ 메소드도 두 개의 매개변수를 받지만 이는 내부 작업입니다. 즉, 첫 번째 매개변수의 값을 변경한다는 의미입니다. 왜냐하면 객체가 변경 가능해야 하므로 불변이 필요하지 않기 때문입니다. 객체 __iadd__ 메소드.
>>> hasattr(int, '__iadd__') False >>> hasattr(list, '__iadd__') True
분명히 정수 객체에는 __iadd__가 없지만 목록 객체는 __iadd__ 메서드를 제공합니다.
>>> l2 += [3] # 代码1:使用__iadd__,l2的值原地修改
코드 1의 += 연산은 __iadd__ 메서드를 호출하여 l2가 가리키는 객체의 값을 제자리에서 수정합니다.
>>> l2 = l2 + [3] # 代码2:调用 __add__,创建了一个新的列表,赋值给了l2
위는 i += x와 i = i + x라는 표현의 차이점입니다. 따라서 목록에서 += 작업을 수행할 때 잠재적인 버그가 있을 수 있습니다. 왜냐하면 함수의 매개변수가 변수 개체를 키워드 매개변수로 사용해서는 안 되는 것처럼 l1이 l2의 변경으로 인해 변경되기 때문입니다.