2009-09-08 3 views
53

왜 파이썬에서 "hello" is "hello" == True입니까? Python : 왜 ("hello"가 "hello"인지) True로 평가합니까?

가 나는 here 다음 읽기 :

이 경우 문자열 리터럴들이이 같은 메모리 위치에 넣어되었습니다 동일하다. 문자열은 변경 불가능한 개체입니다. 아무런 해를 끼치 지 않고 할 수 있습니다.

그래서 모든 파이썬 문자열마다 하나의 메모리가 있습니다. 꽤 이상하게 들린다. 무슨 일 이니?

+0

대신 여기를 참조하십시오. http : //pyref.infogami.com/intern – bzlm

+0

또한 메모리 위치를 확인하기위한'id' 함수를보십시오 :'print id ("hello")' – Blixt

+0

bzlm, pyref.infogami.com/intern 링크는 죽었지 만 archive.org는 여기에 복사하십시오 :
http://web.archive.org/web/20090429040354/http://pyref.infogami.com/intern
그러나 종종 사실이지만, 사실은 아닙니다. @bobince는 매우 시연했습니다. 잘 아래에. –

답변

80

파이썬 (예 : Java, C, C++, .NET)은 문자열 풀링/인터 네킹을 사용합니다. 인터프리터는 "hello"는 "hello"와 동일하므로 메모리의 동일한 위치를 최적화하고 사용합니다.

또 다른 고맙기는 "지옥"+ "O" "안녕하세요"==> 진정한

+23

C/C++조차도 일반적으로 이렇게합니다. "foo"== "foo"는 C에서 종종 사실입니다. C와 Python에서 이것은 구현 세부 사항입니다. 나는 파이썬 *에서 인터프리터가 이것을 필요로하지 않는다고 생각한다. C/C++에서 이것은 모든 컴파일러가 할 수있는 최적화가 아니고 사용할 수없는 최적화이다. (대조적으로,이 속성은 루아에서 * 항상 * true입니다. 모든 문자열은 허용되지 않습니다.) –

+2

@Glenn, 정확하고 누군가 언급했기 때문에 기쁩니다. 확실히이 사실에 대해 아무도 믿어서는 안됩니다. – Triptych

+0

컴파일 시간 결정 문자열을 동일하게 만들어이 최적화를 수행하는 것은 c/C++ 특정 작업과 같은 언어 용 인터프리터 또는 컴파일러입니다. – andy

1

왜 이상합니까? 문자열이 변경되지 않으면 한 번만 저장하는 것이 좋습니다. .NET은 동일한 동작을합니다.

+1

문자열 인턴은 불변성과 어떤 관련이 있습니까? 파이썬과 ".NET"둘 다 많은 것들이 인턴 없이는 변경되지 않습니다. – bzlm

+1

문자열 리터럴이 메모리에서 변경 될 수있는 경우이를 공유 할 수 없기 때문에 (또는 "인턴 된"). – harto

+0

사실, 개체가 불변이라는 사실을 고려하면 인스턴스에 대한 참조를 안전하게 공유 할 수 있습니다. –

2

파이썬 인터프리터/컴파일러는 문자열 리터럴, 문자, 즉 인용 목록을 구문 분석이다. 이 작업을 수행하면 "이전에이 문자열을 보았습니다"를 감지하고 마지막으로 동일한 표현을 사용합니다. 이 방법으로 정의 된 문자열을 변경할 수 없다는 것을 알고 있기 때문에이 작업을 수행 할 수 있습니다.

14

리터럴 문자열은 해시 또는 유사한 항목을 기반으로 그룹화되어있을 수 있습니다. 동일한 리터럴 문자열 중 두 개가 동일한 메모리에 저장되며 모든 참조는 모두이를 참조합니다.

Memory  Code 
------- 
|   myLine = "hello" 
|  /
|hello < 
|  \ 
|   myLine = "hello" 
------- 
+2

이것은 받아 들여진 대답이 말하는 것입니다 ... – Martin

+2

악의적 인 downvotes에 대응하는 Upvote – Martin

+4

+1 : 받아 들인 대답은 좋은 ASCII 예술을 가지고 있지 않습니다 :-) – kriss

6

is 연산자는 두 인수가 같은 개체 인 경우 true를 반환합니다. 결과는이 결과와 따옴표 붙은 비트입니다.

문자열 리터럴의 경우 이러한 문자열은 알려진 문자열과 비교되는 의미로 사용됩니다. 동일한 문자열이 이미 알려진 경우 리터럴은 다른 값 대신 해당 값을 사용합니다. 따라서, 그것들은 같은 대상이되고 표현은 사실입니다.

+0

그들은 "같은 대상이됩니다"? 하나를 수정하면 다른 하나는 수정되지 않습니다. – endolith

+3

@endolith : 문제의 객체는 해당 문자열에 할당 된 변수가 아니라 인턴 된 문자열입니다. 파이썬에서 문자열을 수정하는 방법은 없습니다. – SingleNegationElimination

57

그래서 모든 파이썬 문자열마다 하나의 메모리가 있습니다.

아니오, 인터프리터가 최적화하기로 결정한 것은 언어 사양의 일부가 아니며 다른 CPython 버전에서 변경 될 수있는 정책에 기반한 결정입니다.

예 : 내에서합니다 (2.6.2 리눅스) 설치 :의 int에 대한 유사

>>> 'X'*10 is 'X'*10 
True 
>>> 'X'*30 is 'X'*30 
False 

:

>>> 2**8 is 2**8 
True 
>>> 2**9 is 2**9 
False 

그래서 '문자열'에 의존하지 않는 '문자열'입니다 : 심지어 단지 C 구현 그것을보고 안전하지 않습니다.

+11

따라서 문자열 동일성 비교에는 항상'=='을 사용해야합니다. – SingleNegationElimination

+0

인터프리터는 파이썬에서 작은 정수 (최대 256 자)를 캐시합니다. 그래서, 'a = 50; b = 50; a는 b가 True이면 'a = 500; b = 500; a is b is False입니다. –

0

나는 두 변수 (단지 문자열) 같은 값을 포함하는 경우, 값이 한 번하지 두 번 저장되고 두 변수가 같은 위치를 가리 것이라 생각합니다. 이렇게하면 메모리를 절약 할 수 있습니다.

+0

사실이 아닙니다! 그것은 문자열과 작은 정수만 고려합니다. 예를 들어 목록이나 사전의 복사본을 만들 때 같은 값 (== 평등)을 갖더라도 같은 개체가 아닙니다 ("is"평등). 그래서 원본이 변경되지 않은 상태로 목록의 복사본을 변경할 수 있습니다 (또는 그 반대). 훌륭한 설명은 O'reilly의 Learning Python의 Dynamic Typing 장에서 제공됩니다. – fanny