[PYTHON] 무한 중첩 목록에서 정확히 무슨 일이 일어나고 있습니까?
PYTHON무한 중첩 목록에서 정확히 무슨 일이 일어나고 있습니까?
파이썬에서 무한 중첩리스트를 만드는 것이 가능합니다. 그것은 분명하고 대중적이지는 않지만 명확하지는 않지만 알려진 사실입니다.
>>> a = [0]
>>> a[0] = a
>>> a
[[...]]
>>> a[0] == a
True
제 질문은, 여기서 일어나는 일입니다.
>>> a = [0]
>>> b = [0]
>>> a[0], b[0] = b, a
>>> a
[[[...]]]
>>> b
[[[...]]]
>>> a == b
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RuntimeError: maximum recursion depth exceeded in cmp
>>> a[0] == b
True
>>> a[0][0] == b
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RuntimeError: maximum recursion depth exceeded in cmp
>>> a[0][0][0] == b
True
>>>
더 깊은 곳에서, 내가 그것을 이해하려고 할 때, 나는 나의 뇌가 폭발 할 것 같은 느낌을 더줍니다. 나는 a가 a를 포함하고 b를 포함하는 것을 본다.
이제이 질문에 대한 나의 질문. 우리는 정말로 여기에 두 가지 목록을 가지고 있습니까? 어떻게 이런 일이 메모리에 저장 되나요? 프로그래머가 이렇게 이상한 것을 구현할 수있게하는 목적은 무엇일까요?
제발,이 질문을 매우 심각하게 생각하지 마십시오. 잊지 말라. 프로그래밍은 때때로 재미있을 수있다.
해결법
-
==============================
1.면책 조항 : 저는 파이썬을 사용하지 않습니다, 그래서 제가 말하는 것은 틀릴 수도 있습니다. 파이썬 전문가는 저를 시정 해 줄 것입니다.
면책 조항 : 저는 파이썬을 사용하지 않습니다, 그래서 제가 말하는 것은 틀릴 수도 있습니다. 파이썬 전문가는 저를 시정 해 줄 것입니다.
좋은 질문입니다. 나는 중앙 오개념 (만약 내가 그것을 심지어 호출 할 수 없다면, 당신이 사용한 사고 과정에 어떻게 도달했는지 완벽하게 합리적이라고 생각한다)을 묻는 질문을하는 것이 이것이다.
b [0] = a라고 쓸 때, a가 b에 있음을 의미하지는 않습니다. 그것은 b가 가리키는 것을 가리키는 참조를 포함한다는 것을 의미합니다.
변수 a와 b 자체는 "사물"자체조차도 아니며, 메모리 자체의 익명의 "사물"에 대한 포인터이기도합니다.
참조 개념은 비 프로그래밍 세계에서 큰 도약이므로이 점을 염두에두고 프로그램을 단계별로 살펴 보겠습니다.
>>> a = [0]
당신은 무언가를 가지고있는 목록을 생성합니다 (지금은 무시하십시오). 중요한 것은 목록입니다. 그 목록은 메모리에 저장됩니다. 메모리 위치 1001에 저장되어 있다고 가정 해 봅니다. 그런 다음 할당 =은 프로그래밍 언어에서 나중에 사용할 수있는 변수 a를 만듭니다. 이 시점에서 메모리에 몇 가지 목록 객체가 있으며 그 객체에 대한 참조는 이름으로 액세스 할 수 있습니다.
>>> b = [0]
이것은 b와 같은 일을합니다. 메모리 위치 (1002)에 저장되는 새로운리스트가있다. 프로그래밍 언어는 메모리 위치 및 차례로리스트 객체를 참조하는데 사용할 수있는 참조 b를 생성한다.
>>> a[0], b[0] = b, a
이것은 두 가지가 동일하므로 하나에 초점을 맞추어 보겠습니다. a [0] = b. 이것이하는 일은 꽤 환상적입니다. 그것은 먼저 평등의 오른쪽을 평가하고 변수 b를보고 b가 메모리에 대한 참조이므로 메모리 (메모리 객체 # 1002)에서 해당 객체를 가져옵니다. 왼쪽에서 일어나는 일은 똑같이 환상적입니다. a는리스트 (메모리 오브젝트 # 1001)를 가리키는 변수이지만, 메모리 오브젝트 # 1001 그 자체는 다수의 자체 참조를가집니다. 여러분이 사용하는 a와 b와 같은 이름을 가진 레퍼런스 대신 0과 같은 숫자 인덱스를 사용합니다. 따라서 지금은 인덱스 된 레퍼런스 더미 인 메모리 오브젝트 # 1001을 가져옵니다. 인덱스 0 (이전에는이 참조가 실제 숫자 0을 가리켰습니다.이 값은 1 행에서 수행 한 것입니다). 그런 다음 해당 참조 (즉, 메모리 오브젝트 # 1001의 첫 번째 및 유일한 참조)를 방정식의 오른쪽에있는 값은로 평가됩니다. 이제 개체 # 1001의 0 번째 참조가 개체 # 1002를 가리 킵니다.
>>> a [[[...]]] >>> b [[[...]]]
이것은 프로그래밍 언어에 의해 완성 된 단지 환상입니다. a를 평가하도록 요청하면 메모리 오브젝트 (위치 # 1001의 목록)를 위로 당기고, 자신의 마법을 사용하여 무한하다는 것을 감지하고 그 자체로 렌더링합니다.
>>> a == b Traceback (most recent call last): File "<stdin>", line 1, in <module> RuntimeError: maximum recursion depth exceeded in cmp
이 문장의 실패는 파이썬이 어떻게 비교하는지와 관련이있다. 객체를 자체 객체와 비교하면 즉시 true로 평가됩니다. 다른 개체와 비교하고 반대 할 때 "마법"을 사용하여 등호가 참인지 거짓인지를 결정합니다. 파이썬의 목록의 경우, 각 목록의 모든 항목을 살펴본 후 항목의 등호 검사 방법을 사용하여 항목이 같은지 확인합니다. 그래서, 시도 할 때 == b. 그것이하는 일은 먼저 b (객체 # 1002)와 (객체 # 1001)을 파고 메모리에서 다른 것들이 있다는 것을 깨닫고 재귀 목록 검사기로 간다. 이 작업은 두 목록을 반복하여 수행합니다. 오브젝트 # 1001에는 오브젝트 # 1002를 가리키는 인덱스 0의 요소가 하나 있습니다. 오브젝트 # 1002에는 오브젝트 # 1001을 가리키는 인덱스 0의 요소가 하나 있습니다. 따라서 프로그램은 # 1001과 # 1002가 모두 같은 점을 가리킨다면 # 1002 (# 1001의 유일한 참조 점)와 # 1001 (# 1002의 유일한 참조 점)은 같다고 결론 짓는다. 똑같은 것. 이러한 동등성 검사는 결코 멈출 수 없습니다. 멈추지 않는 목록에서도 똑같은 일이 일어날 것입니다. 당신은 할 수있는 c = [0]; d = [0]; c [0] = d; d [0] = c 및 a == c는 동일한 오류를 발생시킵니다.
>>> a[0] == b True
앞 단락에서 암시 한 바와 같이, 파이썬이 바로 가기를 취하기 때문에이 사실은 즉시 해결됩니다. [0]은 객체 # 1002를 가리키고 b는 객체 # 1002를 가리키기 때문에리스트 내용을 비교할 필요가 없습니다. 파이썬은 문자 적 의미에서 동일하다는 것을 감지하고 (동일한 "것") 내용을 확인하는 것을 방해하지 않습니다.
>>> a[0][0] == b Traceback (most recent call last): File "<stdin>", line 1, in <module> RuntimeError: maximum recursion depth exceeded in cmp
[0] [0]이 오브젝트 # 1001을 가리 키기 때문에 이것은 오류가됩니다. 신원 확인이 실패하고 다시 끝나는 절대적 컨텐트 검사로 되돌아갑니다.
>>> a[0][0][0] == b True
다시 한번, [0] [0] [0]은 b와 마찬가지로 객체 # 1002를 가리 킵니다. 재귀 확인은 건너 뛰고 비교는 즉시 true를 반환합니다.
특정 코드 스 니펫과 직접적으로 관련이없는 높은 수준의 jibber jabber :
-
==============================
2.나는 다음과 같은 일이 일어날 것으로 생각한다.
나는 다음과 같은 일이 일어날 것으로 생각한다.
a [0] == b : 파이썬은 값 a [0]을 찾아 b에 대한 일종의 참조를 찾습니다. 그래서 True를 말합니다.
a [0] [0] == b : 파이썬은 a [0]을 찾아 b를 찾고 a [0] [b] b [0]이므로 a [0] [0]을 찾습니다. 이제는 b [0]이 a와 어떤 종류의 참조를 가지고 있다는 것을 보았습니다. 이것은 b와 정확히 같지 않습니다. 따라서 python은 요소를 비교해야합니다. 즉 a [0]과 b [0]을 비교해야합니다. 자, 무한 재귀가 시작됩니다 ...
이것은 [0] = b를 할당 할 때 실제로 파이썬이리스트를 복사하지 않기 때문에 작동합니다. 파이썬은 오히려 [0]에 저장된 b에 대한 참조를 만듭니다.
-
==============================
3.a [0]은 b를 나타내고 b [0]은 a를 나타냅니다. 이것은 순환 참조입니다. glglgl에서 언급했듯이 == 연산자를 사용하면 값의 비교를 수행합니다.
a [0]은 b를 나타내고 b [0]은 a를 나타냅니다. 이것은 순환 참조입니다. glglgl에서 언급했듯이 == 연산자를 사용하면 값의 비교를 수행합니다.
이것을 시도하면 더 명확하게 알 수 있습니다.
>>> id(a) 4299818696 >>> id(b) 4299818768 >>> id(a[0]) 4299818768 >>> >>> id(b[0]) 4299818696
-
==============================
4.그들은 서로를 포함하지 않습니다. A는 목록에 대한 참조이고,이 목록의 첫 번째 것은 B에 대한 참조이고, 그 반대의 경우도 마찬가지입니다.
그들은 서로를 포함하지 않습니다. A는 목록에 대한 참조이고,이 목록의 첫 번째 것은 B에 대한 참조이고, 그 반대의 경우도 마찬가지입니다.
>>> a[0] == b True >>> a[0][0] == b Traceback (most recent call last): File "<stdin>", line 1, in <module> RuntimeError: maximum recursion depth exceeded in cmp >>> a[0][0][0] == b True
원하는만큼 많은 목록 조회를 할 수 있기 때문에 [0]의 개수는 중요하지 않습니다. 중요한 것은 예제 # 1 및 # 3 (그리고 모든 홀수의 조회수)에서 " 파이썬은 메모리 주소를 비교하여 똑같은지 확인합니다. 그렇습니다. 그렇습니다. 예제 # 2 (그리고 모든 짝수 조회)에서 "A가 B와 같습니다"라고 말하면 파이썬은 서로 다른 메모리 주소임을 확인한 다음 전체 (무한) 데이터 구조를 메모리에로드하여보다 많은 인 - 깊이 비교.
-
==============================
5.이들은 두 가지 목록입니다. 먼저, 다음과 같이 만듭니다.
이들은 두 가지 목록입니다. 먼저, 다음과 같이 만듭니다.
a = [0] b = [0]
그런 다음 각 요소를 다른 요소의 첫 번째 요소에 할당합니다.
a[0], b[0] = b, a
그래서 당신은 말할 수 있습니다.
a[0] is b
과
b[0] is a
이것은 첫 번째 예와 동일한 상황이지만 깊이가 더 깊다.
또한 신원 (is)은 같지 않지만 평등 (==)은 비교합니다. 이것은 그들을 비교하려고 시도합니다. 내부 깊숙한 곳, 재귀가되는 곳.
from https://stackoverflow.com/questions/7674685/whats-exactly-happening-in-infinite-nested-lists by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] OpenCV와 두 이미지 결합 (0) | 2018.10.20 |
---|---|
[PYTHON] Python에서 Comet을 이해하는 데 도움이 필요하다 (Django 사용) (0) | 2018.10.20 |
[PYTHON] 어떻게 파이썬에서 문자열 소문자로? (0) | 2018.10.19 |
[PYTHON] 파이썬 / IPython 인터프리터에서 밑줄 _에 값 지정 _ (0) | 2018.10.19 |
[PYTHON] PDF를 이미지로 자동 변환 (0) | 2018.10.19 |