복붙노트

[PYTHON] 고급 중첩 목록 이해 구문

PYTHON

고급 중첩 목록 이해 구문

나는 그들에 대한 더 나은 이해를 얻기 위해리스트 comprehensions로 놀고 있었고, 나는 설명 할 수없는 예상치 못한 결과물을 만났다. 전에 질문 한이 질문을 찾지 못했지만, 그것이 반복되는 질문이라면 사과드립니다.

저는 본질적으로 발전기를 생성하는 발전기를 작성하려고했습니다. 목록 이해력을 사용하는 간단한 생성기는 다음과 같습니다.

(x for x in range(10) if x%2==0) # generates all even integers in range(10)

내가 뭘 하려던 것은 두 개의 생성기를 생성하는 생성기를 작성하는 것입니다. 처음에는 범위 (10)의 짝수를 생성하고 두 번째 생성자는 범위 (10)의 홀수를 생성했습니다. 이것을 위해, 나는했다 :

>>> (x for x in range(10) if x%2==i for i in range(2))
<generator object <genexpr> at 0x7f6b90948f00>

>>> for i in g.next(): print i
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <genexpr>
UnboundLocalError: local variable 'i' referenced before assignment
>>> g.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration
>>> g = (x for x in range(10) if x%2==i for i in range(2))
>>> g
<generator object <genexpr> at 0x7f6b90969730>
>>> g.next()
Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 1, in <genexpr>
    UnboundLocalError: local variable 'i' referenced before assignment

나는 왜 '나'가 과제 전에 참조되고 있는지 이해하지 못한다.

나는 그것이 범위 (2)에서 내가해야 할 일이있을 것이라고 생각했기 때문에 나는 그렇게했다 :

>>> g = (x for x in range(10) if x%2==i for i in [0.1])
>>> g
<generator object <genexpr> at 0x7f6b90948f00>
>>> g.next()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <genexpr>
UnboundLocalError: local variable 'i' referenced before assignment

이것은 나에게 의미가 없었기 때문에, 먼저 더 간단한 것을 시도하는 것이 가장 좋다고 생각했습니다. 그래서 나는 목록으로 돌아가서 다음을 시도했다.

>>> [x for x in range(10) if x%2==i for i in range(2)]
[1, 1, 3, 3, 5, 5, 7, 7, 9, 9]

나는 다음과 같은 것으로 기대했다.

>>> l = []
>>> for i in range(2):
...     for x in range(10):
...             if x%2==i:
...                     l.append(x)
... 
>>> l
[0, 2, 4, 6, 8, 1, 3, 5, 7, 9] # so where is my list comprehension malformed?

그러나 나는 그것을 직감으로 시험해 보았을 때 다음과 같이 작동했습니다.

>>> [[x for x in range(10) if x%2==i] for i in range(2)]
[[0, 2, 4, 6, 8], [1, 3, 5, 7, 9]] # so nested lists in nested list comprehension somehow affect the scope of if statements? :S

그래서 if 문이 어느 수준의 범위에서 작동하는지 문제가 될 수 있다고 생각했습니다. 그래서 이것을 시도했습니다 :

>>> [x for x in range(10) for i in range(2) if x%2==i]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

그리고 지금 나는 완전히 혼란 스럽다. 누군가이 행동을 설명해 주시겠습니까? 내 목록 내포가 잘못된 형식으로 보이는 이유를 이해하지 못하거나 if 문 범위가 작동하는 방식을 이해하지 못합니다.

추신 : 질문을 증명하는 동안, 나는 이것이 숙제 문제처럼 보임을 깨달았습니다. 그렇지 않습니다.

해결법

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

    1.괄호를 사용해야합니다.

    괄호를 사용해야합니다.

    ((x for x in range(10) if x%2==i) for i in range(2))
    

    이전 목록의 이해력이 i 변수를 둘러싼 범위로 누설하고 현재 범위의 i가 되었기 때문에 효과가있었습니다. 새로운 파이썬 인터프리터를 시작하면 NameError로 인해 실패합니다. 카운터의 누수 동작은 Python 3에서 제거되었습니다.

    편집하다:

    다음과 같은 for 루프 :

    (x for x in range(10) if x%2==i for i in range(2))
    

    다음과 같습니다 :

    l = []
    for x in range(10):
        if x%2 == i:
            for i in range(2):
                l.append(x)
    

    또한 이름 오류를 제공합니다.

    EDIT2 :

    괄호 안의 버전 :

    ((x for x in range(10) if x%2==i) for i in range(2))
    

    다음과 같습니다.

    li = []
    for i in range(2):
        lx = []
        for x in range(10):
            if x%2==i:
                lx.append(x)
        li.append(lx)
    
  2. ==============================

    2.Ryan Ryan의 for-loop에 해당하는 것은 다음과 같은 결과를 낳았습니다.

    Ryan Ryan의 for-loop에 해당하는 것은 다음과 같은 결과를 낳았습니다.

    [x for i in range(2) for x in range(10) if i == x%2]
    

    산출물

    [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]
    
  3. ==============================

    3.Lie Ryan의 대답을 약간 확장하면 다음과 같습니다.

    Lie Ryan의 대답을 약간 확장하면 다음과 같습니다.

    뭔가 = (범위 (2)에있는 x % 2 == i 인 경우 범위 (10)의 x에 대한 x)

    다음과 같습니다.

    def _gen1():
        for x in range(10):
            if x%2 == i:
                for i in range(2):
                    yield x
    something = _gen1()
    

    괄호로 묶인 버전은 다음과 같습니다.

    def _gen1():
        def _gen2():
            for x in range(10):
                if x%2 == i:
                    yield x
    
        for i in range(2):
            yield _gen2()
    something = _gen1()
    

    이것은 실제로 두 개의 생성기를 생성합니다.

    [<generator object <genexpr> at 0x02A0A968>, <generator object <genexpr> at 0x02A0A990>]
    

    불행히도 출력은 생성 방법에 따라 출력이 다소 불안정합니다.

    >>> gens = ((x for x in range(10) if x%2==i) for i in range(2))
    >>> for g in gens:
            print(list(g))
    
    [0, 2, 4, 6, 8]
    [1, 3, 5, 7, 9]
    >>> gens = ((x for x in range(10) if x%2==i) for i in range(2))
    >>> for g in list(gens):
            print(list(g))
    
    [1, 3, 5, 7, 9]
    [1, 3, 5, 7, 9]
    

    내 충고는 생성기 함수를 전부 작성하는 것입니다. 그 일을하지 않고 올바른 범위 지정을 시도하는 것이 불가능할 수도 있습니다.

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

    4.거짓말은 구문 론적 질문에 답을줍니다. 제안 : 발전기의 몸에 많은 것을 넣지 마십시오. 함수가 훨씬 더 읽기 쉽습니다.

    거짓말은 구문 론적 질문에 답을줍니다. 제안 : 발전기의 몸에 많은 것을 넣지 마십시오. 함수가 훨씬 더 읽기 쉽습니다.

    def make_generator(modulus):
        return (x for x in range(10) if x % 2 == modulus)
    g = (make_generator(i) for i in range(2))
    
  5. from https://stackoverflow.com/questions/3766711/advanced-nested-list-comprehension-syntax by cc-by-sa and MIT license