복붙노트

[PYTHON] 'is'연산자는 문자열을 공백으로 비교할 때 다르게 동작합니다.

PYTHON

'is'연산자는 문자열을 공백으로 비교할 때 다르게 동작합니다.

Python (Python 3.3)을 배우기 시작했고 is 연산자를 사용해 보았습니다. 나는 이것을 시도했다 :

>>> b = 'is it the space?'
>>> a = 'is it the space?'
>>> a is b
False
>>> c = 'isitthespace'
>>> d = 'isitthespace'
>>> c is d
True
>>> e = 'isitthespace?'
>>> f = 'isitthespace?'
>>> e is f
False

그것은 공간과 물음표가 행동을 다르게 만드는 것처럼 보입니다. 무슨 일이야?

편집 : 나는 ==를 사용해야한다는 것을 알고, 나는 왜 이런 행동을하는지 알고 싶었다.

해결법

  1. ==============================

    1.경고 :이 답변은 특정 파이썬 인터프리터의 구현 세부 사항에 관한 것입니다. 문자열을 == 나쁜 아이디어라고 비교합니다.

    경고 :이 답변은 특정 파이썬 인터프리터의 구현 세부 사항에 관한 것입니다. 문자열을 == 나쁜 아이디어라고 비교합니다.

    음, 적어도 cpython3.4 / 2.7.3의 경우 대답은 "아니오, 공백이 아닙니다"입니다. 공백뿐만 아니라 :

    영숫자 문자열 리터럴은 항상 메모리를 공유합니다.

    >>> x='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
    >>> y='aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
    >>> x is y
    True
    

    영숫자가 아닌 문자열 리터럴은 둘러싼 구문 블록을 공유하는 경우에만 메모리를 공유합니다.

    (통역사)

    >>> x='`!@#$%^&*() \][=-. >:"?<a'; y='`!@#$%^&*() \][=-. >:"?<a';
    >>> z='`!@#$%^&*() \][=-. >:"?<a';
    >>> x is y
    True 
    >>> x is z
    False 
    

    (파일)

    x='`!@#$%^&*() \][=-. >:"?<a';
    y='`!@#$%^&*() \][=-. >:"?<a';
    z=(lambda : '`!@#$%^&*() \][=-. >:"?<a')()
    print(x is y)
    print(x is z)
    

    출력 : 참 및 거짓

    간단한 바이너리 연산의 경우, 컴파일러는 매우 간단한 상수 전파 (peephole.c 참조)를 수행하지만 문자열의 경우 결과 문자열이 21 개의 문자보다 짧은 경우에만 수행합니다. 이 경우 앞서 언급 한 규칙이 적용됩니다.

    >>> 'a'*10+'a'*10 is 'a'*20
    True
    >>> 'a'*21 is 'a'*21
    False
    >>> 'aaaaaaaaaaaaaaaaaaaaa' is 'aaaaaaaa' + 'aaaaaaaaaaaaa'
    False
    >>> t=2; 'a'*t is 'aa'
    False
    >>> 'a'.__add__('a') is 'aa'
    False
    >>> x='a' ; x+='a'; x is 'aa'
    False
    

    단일 문자는 항상 메모리를 공유합니다. 물론 :

    >>> chr(0x20) is ' '
    True
    
  2. ==============================

    2.Ignacio의 대답을 약간 확장하면 다음과 같습니다. is 연산자는 ID 연산자입니다. 객체 식별을 비교하는 데 사용됩니다. 같은 내용으로 두 개의 객체를 구성하면 객체 ID가 true가 아닌 경우가 일반적입니다. 파이썬의 참조 구현 인 CPython은 내용을 개별적으로 저장하므로 모든 객체가 동일한 문자열 컨텐츠를 참조하기 때문에 일부 작은 문자열에서 작동합니다. 따라서 is 연산자는 해당 연산자에 대해 true를 반환합니다.

    Ignacio의 대답을 약간 확장하면 다음과 같습니다. is 연산자는 ID 연산자입니다. 객체 식별을 비교하는 데 사용됩니다. 같은 내용으로 두 개의 객체를 구성하면 객체 ID가 true가 아닌 경우가 일반적입니다. 파이썬의 참조 구현 인 CPython은 내용을 개별적으로 저장하므로 모든 객체가 동일한 문자열 컨텐츠를 참조하기 때문에 일부 작은 문자열에서 작동합니다. 따라서 is 연산자는 해당 연산자에 대해 true를 반환합니다.

    그러나 이것은 CPython의 구현 세부 사항이며 일반적으로 CPython이나 기타 구현에 대해 보장되지 않습니다. 따라서이 사실을 사용하는 것은 다른 어떤 날을 깨뜨릴 수있는 나쁜 생각입니다.

    문자열을 비교하려면 == 연산자를 사용합니다.이 연산자는 객체의 평등을 비교합니다. 두 문자열 객체는 동일한 문자를 포함 할 때 동등한 것으로 간주됩니다. 따라서 이것은 문자열을 비교할 때 사용할 올바른 연산자이며 객체 식별자를 명시 적으로 원하지 않으면 일반적으로 피해야합니다 (예 : a가 False).

    세부 사항에 정말로 관심이 있다면 CPython의 문자열 구현을 여기서 찾을 수 있습니다. 그러나 다시 말하지만 이것은 구현 세부 사항이므로이 작업을 요구하지 않아야합니다.

  3. ==============================

    3.is 연산자는 동시에 존재하는 객체들 사이에서 유일한 것으로 보장되는 id 함수에 의존합니다. 특히 id는 객체의 메모리 주소를 반환합니다. CPython은 문자 a-z와 A-Z 만 포함하는 문자열에 일관된 메모리 주소를 가지고있는 것으로 보입니다.

    is 연산자는 동시에 존재하는 객체들 사이에서 유일한 것으로 보장되는 id 함수에 의존합니다. 특히 id는 객체의 메모리 주소를 반환합니다. CPython은 문자 a-z와 A-Z 만 포함하는 문자열에 일관된 메모리 주소를 가지고있는 것으로 보입니다.

    그러나 이것은 문자열이 변수에 할당 된 경우에만 나타나는 것으로 보입니다.

    여기에서 "foo"의 id와 a의 id는 동일합니다. a는 id를 검사하기 전에 "foo"로 설정되었습니다.

    >>> a = "foo"
    >>> id(a)
    4322269384
    >>> id("foo")
    4322269384
    

    그러나, "bar"의 id와 "a"의 id는 "bar"와 동일하게 설정하기 전에 "bar"의 id를 검사 할 때와 다릅니다.

    >>> id("bar")
    4322269224
    >>> a = "bar"
    >>> id(a)
    4322268984
    

    "bar"와 동일한 값을 설정 한 후 "bar"의 id를 다시 확인하면 동일한 id를 반환합니다.

    >>> id("bar")
    4322268984
    

    따라서 cPython은 문자열이 변수에 할당 될 때 a-zA-Z 만 포함 된 문자열에 대해 일관된 메모리 주소를 유지하는 것으로 보입니다. 그것은 또한 전적으로 버전에 따라 달라질 수 있습니다 : 나는 맥북에 파이썬 2.7.3을 실행 중입니다. 다른 것은 완전히 다른 결과를 얻을 수 있습니다.

  4. ==============================

    4.사실 귀하의 코드는 객체 id (즉, 물리적 주소)를 비교합니다. 그래서 당신 대신 비교 :

    사실 귀하의 코드는 객체 id (즉, 물리적 주소)를 비교합니다. 그래서 당신 대신 비교 :

    >>> b = 'is it the space?'
    >>> a = 'is it the space?'
    >>> a is b
    False
    

    넌 할 수있어:

    >>> id(a) == id(b)
    False
    

    그러나 a와 b가 비교에 직접 존재한다면 그것은 효과가있다.

    >>> id('is it the space?') == id('is it the space?')
    True
    

    실제로 표현식에는 동일한 정적 문자열간에 공유가 있습니다. 그러나 프로그램 규모에서는 단어와 같은 문자열 (공백이나 문장 부호는 사용하지 않음) 만 공유합니다.

    어디서나 문서화되지 않았으므로 구현의 세부 사항이므로이 동작에 의존해서는 안됩니다.

  5. ==============================

    5.'is'연산자는 실제 객체를 비교합니다.

    'is'연산자는 실제 객체를 비교합니다.

    c는 d도 거짓이어야합니다. 내 생각 엔, 파이썬은 최적화를하고 그 경우에는 같은 객체이다.

  6. from https://stackoverflow.com/questions/16756699/is-operator-behaves-differently-when-comparing-strings-with-spaces by cc-by-sa and MIT license