IT story

빈 목록 (예 : [] =“”)에 할당하지 않아도 오류가 발생하는 이유는 무엇입니까?

hot-time 2020. 8. 2. 17:21
반응형

빈 목록 (예 : [] =“”)에 할당하지 않아도 오류가 발생하는 이유는 무엇입니까?


파이썬 3.4에서 입력하고 있습니다

[] = "" 

제대로 작동하지만 예외가 발생하지 않습니다. 물론 나중에 []는 같지 않습니다 "".

[] = ()

또한 잘 작동합니다.

"" = []

그래도 예상대로 예외가 발생합니다.

() = ""

그래도 예상대로 예외를 발생시킵니다. 무슨 일이야?


평등을 비교하지 않습니다. 님을 할당하고 있습니다.

Python을 사용하면 여러 대상에 할당 할 수 있습니다.

foo, bar = 1, 2

두 값을 각각 foo및에 할당합니다 bar. 오른쪽 에는 시퀀스 또는 반복 가능 하고 왼쪽에는 목록 또는 튜플이 필요합니다.

할 때 :

[] = ""

빈 이름 목록에 시퀀스 (빈 문자열은 여전히 ​​시퀀스 임)를 할당했습니다 .

본질적으로 다음과 같습니다.

[foo, bar, baz] = "abc"

어디와 끝까지 foo = "a", bar = "b"그리고 baz = "c"하지만, 적은 문자.

그러나 문자열에 할당 할 수 없으므로 할당 ""의 왼쪽에서 작동하지 않으며 항상 구문 오류입니다.

지정 문 문서를 참조하십시오 .

대 입문은 표현식 목록을 평가하고 (이것은 단일 표현식 또는 쉼표로 구분 된 목록이며, 후자는 튜플을 생성 함을 기억하십시오) 단일 결과 객체를 각 대상 목록에 왼쪽에서 오른쪽으로 할당합니다.

선택적으로 괄호 또는 대괄호로 묶인 대상 목록에 오브젝트를 지정하는 것은 다음과 같이 재귀 적으로 정의됩니다.

강조 광산 .

빈 목록에 대해 파이썬에서 구문 오류가 발생하지 않는다는 것은 실제로 약간의 버그입니다! 공식적으로 문서화 된 문법은 비어있는 대상 목록을 허용하지 않으며, 비어 ()있는 경우 오류가 발생합니다. 버그 23275 참조 ; 무해한 버그로 간주됩니다.

출발점은 이것이 오랫동안 주변에 있었고 무해하다는 것을 인식하고 있습니다.

또한 비어있는 튜플에는 할당하지 않고 빈 목록에 할당하는 것이 왜 유효합니까?를 참조하십시오.


설명서 과제 명세서 섹션 규칙을 따릅니다.

assignment_stmt ::=  (target_list "=")+ (expression_list | yield_expression)

target list대상이 쉼표로 구분 된 대상 목록 인 경우 : 대상 목록에 대상 이있는 것과 동일한 수의 항목으로 오브젝트를 반복 가능해야하며 항목은 왼쪽에서 오른쪽으로 해당 대상에 지정됩니다.

대상 목록에 대상이있는 것과 동일한 수의 항목이있는 시퀀스 여야하며 왼쪽에서 오른쪽으로 해당 대상에 항목이 지정됩니다.

당신이 말할 때

[] = ""

"" iterable (유효한 모든 파이썬 문자열은 iterable)이며 목록의 요소를 통해 압축이 풀립니다.

예를 들어

>>> [a, b, c] = "123"
>>> a, b, c
('1', '2', '3')

빈 문자열과 빈 목록이 있으므로 압축을 풀어야 할 것이 없습니다. 따라서 오류가 없습니다.

그러나 이것을 시도하십시오

>>> [] = "1"
Traceback (most recent call last):
  File "<input>", line 1, in <module>
ValueError: too many values to unpack (expected 0)
>>> [a] = ""
Traceback (most recent call last):
  File "<input>", line 1, in <module>
ValueError: need more than 0 values to unpack

In the [] = "1" case, you are trying to unpack the string "1" over an empty list of variables. So it complains with "too many values to unpack (expected 0)".

Same way, in [a] = "" case, you have an empty string, so nothing to unpack really, but you are unpacking it over one variable, which is, again, not possible. That is why it complains "need more than 0 values to unpack".

Apart from that, as you noticed,

>>> [] = ()

also throws no error, because () is an empty tuple.

>>> ()
()
>>> type(())
<class 'tuple'>

and when it is unpacked over an empty list, there is nothing to unpack. So no error.


But, when you do

>>> "" = []
  File "<input>", line 1
SyntaxError: can't assign to literal
>>> "" = ()
  File "<input>", line 1
SyntaxError: can't assign to literal

as the error message says, you are trying to assign to a string literal. Which is not possible. That is why you are getting the errors. It is like saying

>>> 1 = "one"
  File "<input>", line 1
SyntaxError: can't assign to literal

Internals

Internally, this assignment operation will be translated to UNPACK_SEQUENCE op code,

>>> dis(compile('[] = ""', "string", "exec"))
  1           0 LOAD_CONST               0 ('')
              3 UNPACK_SEQUENCE          0
              6 LOAD_CONST               1 (None)

Here, since the string is empty, UNPACK_SEQUENCE unpacks 0 times. But when you have something like this

>>> dis(compile('[a, b, c] = "123"', "string", "exec"))
  1           0 LOAD_CONST               0 ('123')
              3 UNPACK_SEQUENCE          3
              6 STORE_NAME               0 (a)
              9 STORE_NAME               1 (b)
             12 STORE_NAME               2 (c)
             15 LOAD_CONST               1 (None)
             18 RETURN_VALUE

the sequence 123 is unpacked in to the stack, from right to left. So, the top of the stack would be 1 and the next would be 2 and the last would be 3. Then it assigns from the top of the stack to the variables from the left hand side expression one by one.


BTW, in Python, this is how you can do multiple assignments in the same expression. For example,

a, b, c, d, e, f = u, v, w, x, y, z

this works because, the right hand values are used to construct a tuple and then it will be unpacked over the left hand side values.

>>> dis(compile('a, b, c, d, e, f = u, v, w, x, y, z', "string", "exec"))
  1           0 LOAD_NAME                0 (u)
              3 LOAD_NAME                1 (v)
              6 LOAD_NAME                2 (w)
              9 LOAD_NAME                3 (x)
             12 LOAD_NAME                4 (y)
             15 LOAD_NAME                5 (z)
             18 BUILD_TUPLE              6
             21 UNPACK_SEQUENCE          6
             24 STORE_NAME               6 (a)
             27 STORE_NAME               7 (b)
             30 STORE_NAME               8 (c)
             33 STORE_NAME               9 (d)
             36 STORE_NAME              10 (e)
             39 STORE_NAME              11 (f)
             42 LOAD_CONST               0 (None)
             45 RETURN_VALUE

but the classic swapping technique a, b = b, a uses rotation of elements in the top of the stack. If you have only two or three elements then they are treated with special ROT_TWO and ROT_THREE instructions instead of constructing the tuple and unpacking.

>>> dis(compile('a, b = b, a', "string", "exec"))
  1           0 LOAD_NAME                0 (b)
              3 LOAD_NAME                1 (a)
              6 ROT_TWO
              7 STORE_NAME               1 (a)
             10 STORE_NAME               0 (b)
             13 LOAD_CONST               0 (None)
             16 RETURN_VALUE

참고URL : https://stackoverflow.com/questions/30147165/why-isnt-assigning-to-an-empty-list-e-g-an-error

반응형