programing tip

문자열에 점이있을 때 "is"키워드가 다른 동작을하는 이유는 무엇입니까?

itbloger 2020. 12. 30. 07:43
반응형

문자열에 점이있을 때 "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)

그런 식으로 메모리를 절약하려고 시도하지 않습니다. ids는 다릅니다. 즉, 별개의 객체입니다. 잠재적으로 더 높은 비용과 더 낮은 수익이 있으므로이 구현의 최적화 프로그램의 휴리스틱은 검색을 귀찮게하지 말고 계속 진행하도록 지시합니다.

편집 : 모듈 최상위 수준에서 @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 interned 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 interned 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

반응형