programing tip

왜 (0-6)이 -6 = False입니까?

itbloger 2020. 7. 2. 07:59
반응형

왜 (0-6)이 -6 = False입니까? [복제]


가능한 중복 :
파이썬“is”연산자는 정수로 예기치 않게 동작합니다

오늘 나는 내 프로젝트를 디버깅하려고 시도했으며 몇 시간 동안 분석 한 후에 이것을 얻었습니다.

>>> (0-6) is -6
False

그러나,

>>> (0-5) is -5
True

왜 나에게 설명해 주시겠습니까? 아마도 이것은 일종의 버그이거나 매우 이상한 행동 일 것입니다.

> Python 2.7.3 (default, Apr 24 2012, 00:00:54) [GCC 4.7.0 20120414 (prerelease)] on linux2
>>> type(0-6) 
<type 'int'>
>>> type(-6) 
<type 'int'>
>>> type((0-6) is -6)
<type 'bool'>
>>> 

-5에서 256까지의 모든 정수는 CPython과 동일한 주소를 공유하는 전역 객체로 캐시되므로 is테스트에 통과합니다.

이 아티팩트는 http://www.laurentluce.com/posts/python-integer-objects-implementation/ 에 자세히 설명되어 있으며 http://hg.python.org/cpython/file 에서 현재 소스 코드를 확인할 수 있습니다 . /tip/Objects/longobject.c .

특정 구조는 작은 정수를 참조하고 공유하므로 액세스가 빠릅니다. 정수 객체에 대한 262 개의 포인터 배열입니다. 이 정수 객체는 초기화 중에 위에서 본 정수 객체 블록에 할당됩니다. 작은 정수 범위는 -5에서 256까지입니다. 많은 Python 프로그램은 해당 범위의 정수를 사용하여 많은 시간을 소비하므로 현명한 결정입니다.

이것은 CPython의 구현 세부 사항 일 뿐이며 이에 의존해서는 안됩니다. 예를 들어, PyPyid 는 정수를 구현하여 자체를 리턴하므로 (0-6) is -6내부적으로 "다른 오브젝트"인 경우에도 항상 참입니다. 또한이 정수 캐싱 사용 여부를 구성하고 하한 및 상한을 설정할 수도 있습니다. 그러나 일반적으로 다른 원점에서 검색된 객체는 동일하지 않습니다. 평등을 비교하려면을 사용하십시오 ==.


파이썬은 인터프리터에 -5-256 범위의 정수를 저장합니다.이 정수가 반환되는 정수 객체 풀이 있습니다. 이러한 개체가 동일한 이유 : (0-5)-5있지만 (0-6)-6이가 그 자리에서 만들어집니다있다.

CPython 소스 코드의 소스는 다음과 같습니다.

#define NSMALLPOSINTS           257
#define NSMALLNEGINTS           5
static PyIntObject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS];

( CPython의 소스 코드를 볼 : /trunk/Objects/intobject.c). 소스 코드에는 다음과 같은 주석이 포함됩니다.

/* References to small integers are saved in this array so that they
   can be shared.
   The integers that are saved are those in the range
   -NSMALLNEGINTS (inclusive) to NSMALLPOSINTS (not inclusive).
*/

is오퍼레이터는 그들 (비교한다 -5들은 동일한 오브젝트 (동일한 메모리 위치)이지만 다른 두 새로운 정수 (때문에 동일하게) -6) 다른 메모리 위치에있을 것이다 (그리고 is복귀하지 않을 것이다 True). 하는 것으로 257위의 소스 코드는 양의 정수입니다에 즉 있도록 0 - 256(포함).

( 소스 )


버그가 아닙니다. is평등 테스트가 아닙니다. ==예상 결과를 제공합니다.

이 동작의 기술적 이유는 Python 구현이 동일한 상수 값을 가진 다른 인스턴스를 동일한 객체 또는 다른 객체로 자유롭게 처리 할 수 ​​있기 때문입니다. 사용중인 Python 구현은 메모리를 절약하기 위해 특정 작은 상수가 동일한 객체를 공유하도록 선택합니다. 이 동작은 버전과 동일한 버전이거나 다른 Python 구현에 의존 할 수 없습니다.


CPython은 작은 정수와 작은 문자열을 캐시하고 해당 객체의 모든 인스턴스에 동일한 정보를 제공하기 때문에 발생합니다 id().

(0-5)-5에 같은 값이 id()에 대한 사실이 아니다, 0-6-6

>>> id((0-6))
12064324
>>> id((-6))
12064276
>>> id((0-5))
10022392
>>> id((-5))
10022392

문자열과 유사하게 :

>>> x = 'abc'
>>> y = 'abc'
>>> x is y
True
>>> x = 'a little big string'
>>> y = 'a little big string'
>>> x is y
False

문자열 캐싱에 대한 자세한 내용은 is문자열을 공백과 비교할 때 연산자가 다르게 동작합니다.

참고URL : https://stackoverflow.com/questions/11476190/why-0-6-is-6-false

반응형