중첩/다중 목록 이해 또는 생성기 표현식의 사용 사례입니다.언제가 더 우아한가요?

StackOverflow https://stackoverflow.com/questions/648675

문제

저는 가끔 이런 경우를 봅니다.

(k for k in (j for j in (i for i in xrange(10))))

이제 이것은 정말 내 두뇌를 구부리게 만들고 차라리 이런 식으로 제시되지 않았으면 좋겠습니다.

중첩 루프보다 더 우아하고 읽기 쉬운 이러한 중첩 표현식을 사용한 사용 사례나 예가 있습니까?

편집하다: 이를 단순화하는 방법의 예를 들어주셔서 감사합니다.사실 제가 요청한 건 아닌데, 우아할 때가 있었나 싶었어요.

도움이 되었습니까?

해결책

확인하다 PEP 202 여기서 List Comprehensions Syntax가 언어에 소개되었습니다.

당신의 모범을 이해하기 위해서, Guido 자신의 간단한 규칙이 있습니다.

  • 양식 [... x ... x ... y for y ...] 둥지, 마지막 색인은 루프를 위해 중첩 된 것처럼 가장 빠르게 다양합니다.

또한 PEP 202에서 귀하의 질문에 답하는 데 도움이됩니다.

Rationale
    List comprehensions provide a more concise way to create lists in
    situations where map() and filter() and/or nested loops would
    currently be used.

그런 상황이 있다면 더 우아하다는 것을 알 수 있습니다. 그러나 IMHO는 여러 중첩 목록 이해력이 루프를 위해 중첩 된 것보다 코드에서 명확하지 않을 수 있습니다. for 루프는 시각적으로 쉽게 구문 분석됩니다.

다른 팁

한 줄에 너무 많은 복잡성이 걱정된다면 다음과 같이 분할할 수 있습니다.

(k for k in 
    (j for j in 
        (i for i in xrange(10))))

저는 항상 Python에서 줄 연속이 약간 이상하게 보이는 것을 발견했지만, 이렇게 하면 각 줄이 반복되는 내용을 더 쉽게 확인할 수 있습니다.추가 할당/조회는 아무 것도 만들거나 중단하지 않으므로 다음과 같이 작성할 수도 있습니다.

gen1 = (i for i in xrange(10))
gen2 = (j for j in gen1)
gen3 = (k for k in gen2)

실제로, 나는 2-deep 이상의 comprehension을 중첩한 적이 없다고 생각하는데, 그 시점에서는 여전히 이해하기가 꽤 쉬웠습니다.

귀하의 예제의 경우, 나는 아마도 다음과 같이 쓸 것입니다.

foos = (i for i in xrange(10))
bars = (j for j in foos)
bazs = (k for k in bars)

더 설명적인 이름을 감안할 때, 나는 이것이 아마도 분명 할 것이라고 생각하며, 측정 가능한 성능 차이가 있다고 생각할 수 없습니다.

아마도 당신은 다음과 같은 표현을 더 많이 생각하고있을 것입니다.

(x for x in xs for xs in ys for ys in lst)

- 사실, 그것은 유효하지 않습니다. 다른 순서로 물건을 넣어야합니다.

(x for ys in lst for xs in ys for x in xs)

나는 목록을 평평하게하는 빠른 방법으로 글을 쓸 수도 있지만 일반적으로 당신은 글을 쓰고 있다고 생각합니다. 덜 입력하여 저장하는 시간은 일반적으로 발전기 표현식을 올바르게하는 데 소비하는 여분의 시간으로 균형을 이룹니다.

그것들은 발전기 표현식이기 때문에 각각 자체 이름에 바인딩하여 성능의 변화없이 더 읽을 수 있도록 할 수 있습니다. 중첩 루프로 변경하는 것은 성능에 해를 끼칠 수 있습니다.

irange = (i for i in xrange(10))
jrange = (j for j in irange)
krange = (k for k in jrange)

당신이 선택한 것은 중요하지 않습니다. 나는 멀티 라인 예제가 일반적으로 더 읽기 쉬운 것 같습니다.

경고 : 우아함은 부분적으로 맛의 문제입니다.

목록 이해는 더 이상 절대 없습니다 분명한 루프에 대한 해당 확장보다. 루프도 더 많습니다 강한 목록 이해보다. 그렇다면 왜 그것들을 전혀 사용하지 않습니까?

목록 이해력은 무엇입니까? 간결한 - 그들은 당신이 한 줄로 무언가를 할 수 있습니다.

목록 이해력을 사용하는 시간은 특정 목록이 필요할 때, 상당히 쉽게 쉽게 만들 수 있으며, 중간 물체를 원하거나 필요로하지 않습니다. 이것은 현재 범위의 일부 객체를 단일 객체로 패키지 해야하는 경우 다음과 같이 기능에 공급할 수있는 경우 발생할 수 있습니다.

list1 = ['foo', 'bar']
list2 = ['-ness', '-ity']
return filterRealWords([str1+str2 for str1 in list1 for str2 in list2])

이 코드는 확장 버전보다 읽기 쉬운 것이지만 훨씬 짧습니다. 현재 범위에서 한 번만 사용되는 객체를 생성/명명하는 것을 피합니다.

표현식:

(k for k in (j for j in (i for i in xrange(10))))

다음과 같습니다.

(i for i in xrange(10))

거의 동일합니다.

xrange(10)

마지막 변종은 첫 번째 변형보다 우아합니다.

이와 같은 코드가있는 곳에서 유용하고 우아 할 수 있습니다.

output = []
for item in list:
    if item >= 1:
        new = item += 1
        output.append(new)

당신은 다음과 같은 한 라이너로 만들 수 있습니다.

output = [item += 1 for item in list if item >= 1]
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top