왜 파이썬 (또는 불변 데이터 타입)에서 튜플이 필요한가? 신경 쓰나요? 파이썬에서 불변성의이 사업

나는 몇 가지 파이썬 튜토리얼 (파이썬으로 다이빙)과 Python.org의 언어 참조를 읽었습니다. 왜 언어에 튜플이 필요한지 알 수 없습니다.

튜플은 목록이나 세트에 비해 메소드가 없으며 튜플을 세트 또는 목록으로 변환하여 정렬 할 수 있다면 튜플을 사용하는 요점은 무엇입니까?

불변성?

변수가 원래 할당되었을 때와 다른 곳에서 변수에 살고 있는지 왜 신경 쓰나요? 파이썬에서 불변성의이 사업 전체가 지나치게 강조된 것 같습니다.

C / C ++에서 포인터를 할당하고 유효한 메모리를 가리키는 경우 주소를 사용하기 전에 null이 아닌 한 주소가 어디에 있는지 상관하지 않습니다.

해당 변수를 참조 할 때마다 포인터가 여전히 원래 주소를 가리키는 지 여부를 알 필요가 없습니다. 방금 null을 확인하고 사용하거나 사용하지 않습니다.

파이썬에서 문자열 (또는 튜플)을 할당 할 때 x에 할당 한 다음 문자열을 수정하면 왜 원래 객체인지 걱정해야합니까? 변수가 내 데이터를 가리키는 한, 그게 전부입니다.

>>> x='hello'
>>> id(x)
1234567
>>> x='good bye'
>>> id(x)
5432167

x 여전히 내가 원하는 데이터를 참조하는데, 왜 ID가 같거나 다른지 누가 신경 써야합니까?



답변

  1. 불변 객체는 실질적인 최적화를 가능하게합니다. 이것은 아마도 문자열이 Java에서도 불변이고, 파이썬과 거의 별도로 개발되었지만 거의 모든 시간이 실제로 기능하는 언어로 변하지 않는 이유 일 것입니다.

  2. 특히 파이썬에서는 불변의 것만 해시 가능합니다 (따라서 사전의 세트 또는 키의 멤버). 다시 말하지만 최적화는 가능하지만 “실질적인”것 이상입니다 (완전히 변경 가능한 객체를 저장하는 괜찮은 해시 테이블을 디자인하는 것은 악몽입니다. ​​해시하자마자 모든 것을 복사하거나 객체의 해시 여부를 확인하는 악몽) 당신이 마지막으로 그것을 참조한 이후로 변경되었습니다.

최적화 문제의 예 :

$ python -mtimeit '["fee", "fie", "fo", "fum"]'
1000000 loops, best of 3: 0.432 usec per loop
$ python -mtimeit '("fee", "fie", "fo", "fum")'
10000000 loops, best of 3: 0.0563 usec per loop


답변

위의 답변 중 어느 것도 튜플 대 목록의 실제 문제를 지적하지 않았으며, 파이썬에 익숙하지 않은 많은 사람들이 완전히 이해하지 못하는 것 같습니다.

튜플과리스트는 다른 목적으로 사용됩니다. 동종 데이터를 저장합니다. 다음과 같은 목록을 가질 수 있고 있어야합니다.

["Bob", "Joe", "John", "Sam"]

목록을 올바르게 사용하는 이유는 모두 동종 유형의 데이터, 특히 사람들의 이름이기 때문입니다. 그러나 다음과 같은 목록을 작성하십시오.

["Billy", "Bob", "Joe", 42]

그 목록은 한 사람의 이름과 나이입니다. 그것은 한 가지 유형의 데이터가 아닙니다. 해당 정보를 저장하는 올바른 방법은 튜플 또는 객체입니다. 우리에게 몇 가지가 있다고 가정 해 봅시다.

[("Billy", "Bob", "Joe", 42), ("Robert", "", "Smith", 31)]

튜플과리스트의 불변성과 변경 성은 큰 차이점이 아닙니다. 목록은 파일, 이름, 객체와 같은 종류의 항목 목록입니다. 튜플은 다양한 유형의 객체를 그룹화 한 것입니다. 그것들은 다른 용도로 사용되며 많은 파이썬 코더는 튜플의 용도에 대한 목록을 남용합니다.

제발 하지마


편집하다:

나는이 블로그 게시물이 왜 내가 생각했던 것보다 더 나은지에 대해 설명한다고 생각한다 : http://news.e-scribe.com/397


답변

튜플을 세트 또는 목록으로 변환하여 정렬 할 수 있다면 먼저 튜플을 사용하는 요점은 무엇입니까?

이 특별한 경우에는 요점이 없을 것입니다. 이것은 튜플 사용을 고려하는 경우 중 하나가 아니기 때문에 문제가 아닙니다.

지적했듯이 튜플은 변경할 수 없습니다. 불변의 타입을 가지는 이유는 튜플에 적용됩니다 :

  • 복사 효율성 : 불변 개체를 복사하는 대신 별칭을 지정할 수 있습니다 (변수를 참조에 바인딩)
  • 비교 효율성 : 참조 별 복사를 사용하는 경우 컨텐츠가 아닌 위치를 비교하여 두 변수를 비교할 수 있습니다.
  • interning : 변경할 수없는 값의 사본을 하나만 저장해야합니다.
  • 동시 코드에서 불변 객체에 대한 액세스를 동기화 할 필요가 없습니다.
  • const 정확성 : 일부 값은 변경할 수 없습니다. 이것이 (나에게) 불변 유형의 주된 이유입니다.

특정 Python 구현은 위의 모든 기능을 사용하지 않을 수 있습니다.

사전 키는 변경할 수 없어야합니다. 그렇지 않으면 키 개체의 속성을 변경하면 기본 데이터 구조의 변형이 무효화 될 수 있습니다. 따라서 튜플은 잠재적으로 키로 사용될 수 있습니다. 이것은 const 정확성의 결과입니다.

Dive Into Python의튜플 소개 “도 참조하십시오 .


답변

때때로 우리는 객체를 사전 키로 사용하기를 원합니다

무엇의 가치를 들면, 성장 (2.6+)는 최근 튜플 index()count()방법


답변

나는 항상 동일한 기본 데이터 구조 (배열)에 대해 완전히 별개의 두 가지 유형이 어색한 디자인이지만 실제로 실제 문제는 아니라는 것을 알았습니다. (모든 언어에는 사마귀가 있으며 파이썬은 포함되어 있지만 중요한 것은 아닙니다.)

변수가 원래 할당되었을 때와 다른 곳에서 변수에 살고 있는지 왜 신경 쓰나요? 파이썬에서 불변성의이 사업 전체가 지나치게 강조된 것 같습니다.

이것들은 다른 것입니다. 돌연변이 성은 메모리에 저장된 장소와 관련이 없습니다. 그것은 의미 가 가리키는 물건을 변경할 수 있습니다.

파이썬 객체는 생성, 변경 가능 여부에 따라 위치를 변경할 수 없습니다. (정확히 말하면 id ()의 값은 변경 될 수 없습니다. 실제로는 동일합니다.) 변경 가능한 객체의 내부 저장소는 변경 될 수 있지만 숨겨진 구현 세부 사항입니다.

>>> x='hello'
>>> id(x)
1234567
>>> x='good bye'
>>> id(x)
5432167

변수를 수정 ( “변경”)하지 않습니다. 이름이 같은 새 변수를 만들고 이전 변수를 버립니다. 돌연변이 작업과 비교 :

>>> a = [1,2,3]
>>> id(a)
3084599212L
>>> a[1] = 5
>>> a
[1, 5, 3]
>>> id(a)
3084599212L

다른 사람들이 지적했듯이, 이것은 배열을 사전의 키로 사용하고 불변성을 필요로하는 다른 데이터 구조를 허용합니다.

사전의 키를 완전히 변경할 필요는 없습니다. 키로 사용 된 부분 만 변경할 수 없습니다. 일부 용도의 경우 이는 중요한 차이점입니다. 예를 들어, 고유 한 사용자 이름으로 평등과 해시를 비교하는 사용자를 나타내는 클래스를 가질 수 있습니다. 그런 다음 클래스에 다른 변경 가능한 데이터 ( “사용자가 로그인했습니다”등)를 걸 수 있습니다. 이는 동등성 또는 해시에 영향을 미치지 않으므로이를 사전의 키로 사용하는 것이 가능하고 완벽하게 유효합니다. 이것은 파이썬에서 너무 일반적으로 필요하지 않습니다. 나는 몇몇 사람들이 키가 “불변”이어야한다고 주장했기 때문에 지적했다. 이것은 부분적으로 만 정확하다. 그래도 C ++ 맵 및 세트와 함께 이것을 여러 번 사용했습니다.


답변

gnibbler가 의견에서 제안한 것처럼 Guido는 “목록은 동종 데이터, 튜플은 이종 데이터를위한 것”이라는 완전히 받아 들여지지 않은 의견 을 가지고있었습니다 . 물론 많은 반대자들이 이것을 목록의 모든 요소가 같은 유형이어야한다는 의미로 해석했습니다.

나는 다른 사람들 도 과거 와 달리 다르게 보는 것을 좋아합니다 .

blue= 0, 0, 255
alist= ["red", "green", blue]

type (alist [1])! = type (alist [2])인데도리스트가 동질적인 것으로 간주합니다.

요소의 순서를 변경할 수 있고 코드에 문제가없는 경우 (예 : “정렬되어야 함”과 같은 가정) 목록을 사용해야합니다. 그렇지 않으면 ( blue위 의 튜플에서와 같이) 튜플 을 사용해야합니다.


답변

발신자가 전달한 객체가 변경되지 않도록 보장하기 때문에 중요합니다. 이렇게하면 :

a = [1,1,1]
doWork(a)

호출자의 가치의 보장이 없습니다 호출 후를. 하나,

a = (1,1,1)
doWorK(a)

이제 호출자 또는이 코드의 독자로 알고 A는 동일합니다. 이 시나리오의 경우 항상 목록을 복사하여 전달할 수 있지만 이제는보다 의미적인 언어 구성을 사용하는 대신주기를 낭비하고 있습니다.