기존 답변에서 지적되지 않은 또 다른 문제가 있습니다. 파이썬은 두 개의 불변 값을 병합 할 수 있으며 미리 작성된 작은 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()
관용구) 에서만 생성 된 테스트 에만 사용 하십시오 .