이 글에서는 주로 i += x와 i = i + x 표현식이 Python에서 동일한지 여부에 대한 관련 정보를 예제 코드를 통해 자세히 소개하고 있습니다. 필요하신 친구들은 오셔서 아래 구경하시면 됩니다.
서문
최근에 아주 간단해 보이지만 사실 깊은 의미를 지닌 질문을 봤습니다. 그 질문은 i += x 와 i = 였습니다. i + x는 동일합니까? 대답이 '예'라면 축하합니다. 50% 맞습니다. 왜 절반만 맞다고 하시나요? 우리의 일반적인 이해에 따르면 정수 연산과 관련하여 둘 사이에는 유사점이나 차이점이 없지만 목록 연산에서도 동일합니까?
먼저 다음 두 코드를 살펴보세요.
코드 1
>>> l1 = range(3) >>> l2 = l1 >>> l2 += [3] >>> l1 [0, 1, 2, 3] >>> l2 [0, 1, 2, 3]
코드 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의 모든 객체에는 고유 식별자, 유형, 값이라는 세 가지 공통 속성이 있습니다.
고유 식별: 은 메모리에서 개체의 고유성을 식별하는 데 사용됩니다. 개체가 생성된 후에는 변경되지 않습니다.
유형의 고유 식별자: 는 개체가 지원하는 작업을 결정합니다. 예를 들어 목록은 길이 속성과 정수는 그렇지 않습니다. 마찬가지로, 객체의 유형이 결정되면 변경되지 않습니다. type() 함수는 객체의 유형 정보를 반환할 수 있습니다.
객체의 값은 고유 식별자와 다릅니다. 모든 객체 값이 변경 불가능한 것은 아닙니다. 일부 객체의 값은 특정 작업을 통해 변경될 수 있습니다. 변경 가능한 객체(mutable), 값을 변경할 수 없는 객체를 불변 객체(immutable)라고 합니다.
불변 객체(immutable)
불변 객체의 경우 값은 항상 처음 생성되었을 때의 값입니다. 객체에 대한 작업을 수행하면 새 객체가 생성됩니다.
>>> a = 1 >>> id(a) 32574568 >>> a += 1 >>> id(a) 32574544
정수 "1"은 처음에 할당될 때 정수 개체 1을 가리키지만 += 연산이 수행됩니다. 변수 a 마지막으로, 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
추가 작업을 수행한 후에도 객체의 메모리 주소는 변경되지 않으며 x와 y는 여전히 원래의 객체는 그 값이 변경되었다는 것뿐입니다.
가변 객체와 불변 객체를 이해하고 다시 질문 자체로 돌아가서 +=와 +의 차이점은 무엇인가요?
+= 작업은 먼저 개체의 __iadd__ 메서드를 호출하려고 시도합니다. 그런 메서드가 없으면 하자. 먼저 이것을 살펴보세요.
__add__와 __iadd__의 차이점
__add__ 메서드는 두 개를 받습니다. 매개변수 값은 변경되지 않습니다.
__iadd__ 메소드도 두 개의 매개변수를 받지만 이는 내부 작업입니다. 즉, 개체가 변수여야 하므로 첫 번째 매개변수의 값이 변경됩니다. 불변 객체에는 __iadd__ 메소드가 없습니다.
>>> hasattr(int, '__iadd__') False >>> hasattr(list, '__iadd__') True
분명히 정수 개체에는 __iadd__가 없지만 목록 개체는 __iadd__ 메서드를 제공합니다.
아아앙代码1中的 += 操作调用的是__iadd__方法,他会原地修改l2指向的那个对象本身的值
>>> l2 = l2 + [3] # 代码2:调用 __add__,创建了一个新的列表,赋值给了l2
而代码2中的 + 操作调用的是 __add__ 方法,该方法会返回一个新的对象,原来的对象保持不变,l1还是指向原来的对象,而l2已经指向一个新的对象。
以上就是表达式 i += x 与 i = i + x 的区别。因此对于列表进行 += 操作时,会存在潜在的bug,因为l1会因为l2的变化而发生改变,就像函数的参数不宜使用可变对象作为关键字参数一样。
更多详解Python中表达式i += x与i = i + x是否等价相关文章请关注PHP中文网!