문자열에 점이있을 때 "is"키워드가 다른 동작을하는 이유는 무엇입니까?
이 코드를 고려하십시오.
>>> x = "google"
>>> x is "google"
True
>>> x = "google.com"
>>> x is "google.com"
False
>>>
왜 그런가요?
위의 내용이 올바른지 확인하기 위해 방금 Python 2.5.4, 2.6.5, 2.7b2, Windows의 Python 3.1 및 Linux의 Python 2.7b1에서 테스트했습니다.
모두에 걸쳐 일관성이있는 것처럼 보이므로 의도적으로 설계된 것입니다. 내가 뭔가를 놓치고 있습니까?
내 개인 도메인 필터링 스크립트 중 일부에서 실패한 것으로 나타났습니다.
is
를 검증 정체성을 반대하고, 불변 유형의 문자에 부합 파이썬의 구현에 완벽하게 무료 중 하나 가 불변 유형의 새 개체를 만들 거나 (그들 중 일부는 재사용 할 수 있는지 확인하기 위해 해당 유형의 기존 개체를 통해 추구 동일한 기본 개체에 대한 새 참조를 추가하여). 이것은 최적화의 실용적인 선택이며 의미 론적 제약의 영향을 받지 않으므로 코드는 주어진 구현이 어떤 경로를 취할 수 있는지에 의존해서는 안됩니다 (또는 Python의 버그 수정 / 최적화 릴리스로 중단 될 수 있습니다!).
예를 들어 :
>>> import dis
>>> def f():
... x = 'google.com'
... return x is 'google.com'
...
>>> dis.dis(f)
2 0 LOAD_CONST 1 ('google.com')
3 STORE_FAST 0 (x)
3 6 LOAD_FAST 0 (x)
9 LOAD_CONST 1 ('google.com')
12 COMPARE_OP 8 (is)
15 RETURN_VALUE
따라서이 특정 구현에서는 함수 내에서 관찰이 적용되지 않고 리터럴 (모든 리터럴)에 대해 하나의 객체 만 만들어집니다.
>>> f()
True
실용적으로 그것은 함수 내에서 상수의 로컬 테이블을 통과하는 것 (하나로 충분할 때 여러 상수 불변 객체를 만들지 않음으로써 메모리를 절약하기 위해)이 매우 저렴하고 빠르며, 함수가 반복적으로 호출 될 수 있기 때문에 좋은 성능 반환을 제공 할 수 있기 때문입니다. 나중에.
그러나 대화 형 프롬프트에서 매우 동일한 구현 ( 편집 : 원래 모듈의 최상위 수준에서도 발생할 것이라고 생각했지만 @Thomas의 의견이 저를 올바르게 설정했습니다. 나중에 참조) :
>>> x = 'google.com'
>>> y = 'google.com'
>>> id(x), id(y)
(4213000, 4290864)
그런 식으로 메모리를 절약하려고 시도하지 않습니다. id
s는 다릅니다. 즉, 별개의 객체입니다. 잠재적으로 더 높은 비용과 더 낮은 수익이 있으므로이 구현의 최적화 프로그램의 휴리스틱은 검색을 귀찮게하지 말고 계속 진행하도록 지시합니다.
편집 : 모듈 최상위 수준에서 @Thomas의 관찰에 따라 예를 들면 다음과 같습니다.
$ cat aaa.py
x = 'google.com'
y = 'google.com'
print id(x), id(y)
다시이 구현에서 상수 테이블 기반 메모리 최적화를 볼 수 있습니다.
>>> import aaa
4291104 4291104
(@Thomas의 관찰에 따른 편집 끝).
마지막으로 동일한 구현에서 다시 :
>>> x = 'google'
>>> y = 'google'
>>> id(x), id(y)
(2484672, 2484672)
여기서 휴리스틱 스가 다릅니다. 리터럴 문자열이 "식별자 일 수있는 것처럼 보임"이므로 인턴이 필요한 작업에 사용될 수 있습니다. 따라서 옵티마이 저는 어쨌든 인턴을 인턴합니다 (그리고 일단 인턴을 찾으면 검색 속도가 매우 빨라집니다. 강좌). 그리고 실제로 놀랍습니다 ... :
>>> z = intern(x)
>>> id(z)
2484672
...x
has been intern
ed the very first time (as you see, the return value of intern
is the same object as x
and y
, as it has the same id()
). Of course, you shouldn't rely on this either -- the optimizer doesn't have to intern anything automatically, it's just an optimization heuristic; if you need intern
ed string, intern
them explicitly, just to be safe. When you do intern strings explicitly...:
>>> x = intern('google.com')
>>> y = intern('google.com')
>>> id(x), id(y)
(4213000, 4213000)
...then you do ensure exactly the same object (i.e., same id()
) results each and every time -- so you can apply micro-optimizations such as checking with is
rather than ==
(I've hardly ever found the miniscule performance gain to be worth the bother;-).
Edit: just to clarify, here are the kind of performance differences I'm talking about, on a slow Macbook Air...:
$ python -mtimeit -s"a='google';b='google'" 'a==b'
10000000 loops, best of 3: 0.132 usec per loop
$ python -mtimeit -s"a='google';b='google'" 'a is b'
10000000 loops, best of 3: 0.107 usec per loop
$ python -mtimeit -s"a='goo.gle';b='goo.gle'" 'a==b'
10000000 loops, best of 3: 0.132 usec per loop
$ python -mtimeit -s"a='google';b='google'" 'a is b'
10000000 loops, best of 3: 0.106 usec per loop
$ python -mtimeit -s"a=intern('goo.gle');b=intern('goo.gle')" 'a is b'
10000000 loops, best of 3: 0.0966 usec per loop
$ python -mtimeit -s"a=intern('goo.gle');b=intern('goo.gle')" 'a == b'
10000000 loops, best of 3: 0.126 usec per loop
...a few tens of nanoseconds either way, at most. So, worth even thinking about only in the most extreme "optimize the [expletive deleted] out of this [expletive deleted] performance bottleneck" situations!-)
"is" is an identity test. Python has some caching behavior for small integers and (apparently) strings. "is" is best used for singleton testing (ex. None
).
>>> x = "google"
>>> x is "google"
True
>>> id(x)
32553984L
>>> id("google")
32553984L
>>> x = "google.com"
>>> x is "google.com"
False
>>> id(x)
32649320L
>>> id("google.com")
37787888L
ReferenceURL : https://stackoverflow.com/questions/2858603/why-does-the-is-keyword-have-a-different-behavior-when-there-is-a-dot-in-the-s
'programing tip' 카테고리의 다른 글
Threaded Django 작업이 트랜잭션 또는 db 연결을 자동으로 처리하지 않습니까? (0) | 2020.12.30 |
---|---|
이 응답에 대해 getOutputStream ()이 이미 호출되었습니다. (0) | 2020.12.30 |
파이썬에서 오류가 없을 때까지 시도하십시오 (0) | 2020.12.30 |
C ++의 맵에서 첫 번째 값 가져 오기 (0) | 2020.12.30 |
Vim으로 HTML 태그를 접거나 펼치는 방법 (0) | 2020.12.30 |