기존 답변에서 지적되지 않은 또 다른 문제가 있습니다. 파이썬은 두 개의 불변 값을 병합 할 수 있으며 미리 작성된 작은 int 값이 이것이 일어날 수있는 유일한 방법은 아닙니다. 파이썬 구현은 이것을 보장 하지는 않지만 작은 정수 이상의 것을 위해 모두 수행합니다.
한 가지 들어, 빈 같은 다른 미리 만들어진 가치가있다 tuple, str그리고 bytes, 일부 짧은 문자열 (CPython과 3.6, 그것은 256 단일 문자 라틴어 1 문자열이다). 예를 들면 다음과 같습니다.
>>> a = ()
>>> b = ()
>>> a is b
True
또한 사전 생성되지 않은 값도 동일 할 수 있습니다. 다음 예를 고려하십시오.
>>> c = 257
>>> d = 257
>>> c is d
False
>>> e, f = 258, 258
>>> e is f
True
그리고 이것은 int값으로 제한되지 않습니다 .
>>> g, h = 42.23e100, 42.23e100
>>> g is h
True
분명히 CPython에는에 대한 사전 생성 된 float값이 제공되지 않습니다 42.23e100. 무슨 일이야?
CPython의 컴파일러와 같은 일부 알려진 종류의 불변 상수 값을 통합한다 int, float, str, bytes, 동일한 편집 단위이다. 모듈의 경우 전체 모듈은 컴파일 단위이지만 대화식 인터프리터에서 각 명령문은 별도의 컴파일 단위입니다. c및 d별도의 문으로 정의 되므로 해당 값이 병합되지 않습니다. 이후 e와 f같은 문에 정의되어, 그 값이 병합됩니다.
바이트 코드를 디스 어셈블하면 현재 진행중인 작업을 확인할 수 있습니다. 수행하는 함수를 정의한 e, f = 128, 128다음 호출 dis.dis하면 상수 값이 하나 있음을 알 수 있습니다.(128, 128)
>>> def f(): i, j = 258, 258
>>> dis.dis(f)
1 0 LOAD_CONST 2 ((128, 128))
2 UNPACK_SEQUENCE 2
4 STORE_FAST 0 (i)
6 STORE_FAST 1 (j)
8 LOAD_CONST 0 (None)
10 RETURN_VALUE
>>> f.__code__.co_consts
(None, 128, (128, 128))
>>> id(f.__code__.co_consts[1], f.__code__.co_consts[2][0], f.__code__.co_consts[2][1])
4305296480, 4305296480, 4305296480
128바이트 코드에서 실제로 사용하지 않더라도 컴파일러가 상수로 저장 되어 CPython의 컴파일러가 얼마나 적은 최적화를했는지 알 수 있습니다. 즉, 비어 있지 않은 튜플은 실제로 병합되지 않습니다.
>>> k, l = (1, 2), (1, 2)
>>> k is l
False
함수에 그것을 넣어, dis그것은, 그리고 봐 co_consts저기는의 1와 2,이 (1, 2)같은 공유 튜플 1하고 2있지만, 동일하지 않은, 그리고 ((1, 2), (1, 2))두 개의 별개의 동일한 튜플을 가지고 튜플.
CPython이 수행하는 최적화는 문자열 인터 닝입니다. 컴파일러 상수 폴딩과 달리 소스 코드 리터럴로 제한되지 않습니다.
>>> m = 'abc'
>>> n = 'abc'
>>> m is n
True
반면, str유형 및 내부 스토리지 유형 "ascii compact", "compact"또는 "legacy ready"의 문자열로 제한 되며 많은 경우 "ascii compact"만 구속됩니다.
어쨌든 어떤 값이되어야하는지 또는 구별 할 수 없는지에 대한 규칙은 구현마다, 그리고 동일한 구현의 버전간에, 그리고 심지어 동일한 구현의 동일한 사본에서 동일한 코드의 실행 간에도 다양합니다. .
재미를 위해 특정 Python에 대한 규칙을 배우는 것이 좋습니다. 그러나 코드에서 그것들에 의존 할 가치는 없습니다. 유일한 안전한 규칙은 다음과 같습니다.
- 두 동일하지만 별도로 만들어 불변의 값을 사용하지 않는 (동일 가정 쓰지 코드 수행
x is y, 사용x == y )
- 동일하지만 별도로 생성 된 불변 값이 서로 다른 것으로 가정하는 코드를 작성하지 마십시오 (use
x is not y, use x != y)
즉, is문서화 된 싱글 톤 (예 :)을 테스트 None하거나 코드의 한 위치 (예 : _sentinel = object()관용구) 에서만 생성 된 테스트 에만 사용 하십시오 .