수색…


소개

목록 이해는 다음 코드에서 설명하는 것처럼 자연스럽고 간결한 방식으로 목록을 작성하는 구문 도구입니다. 1-10의 제곱의 목록을 만듭니다. [i ** 2 for i in range(1,11)] 기존 목록 range 의 더미 i 는 새 요소 패턴을 만드는 데 사용됩니다. 표현하기 어려운 언어에서 for 루프가 필요한 곳에서 사용됩니다.

통사론

  • [나는 범위 (10) 안에] 기본 목록 이해력
  • [내가 xrange (i)에 대한] 파이썬 2.x에서 생성기 개체를 기본 목록 이해 #
  • [i가 범위 (20) 인 경우 i % 2 == 0] 필터 사용
  • [3, 4, 5]에서 y에 대해 [1, 2, 3에서 x에 대해 x + y] 중첩 된 루프
  • [i가 6보다 큰 경우, 범위 (10)의 i에 대해 0] # 3 진 표현
  • [if i> 4 else if i for range (20) if i % 2 == 0] 필터 및 삼항 표현식 사용
  • [[3, 4, 5]]에서 y에 대한 [[x, y는 [1, 2, 3]에서 x에 대해] 중첩 된 목록 이해력

비고

리스트 comprehension은 PEP 202 에서 개괄되었고 Python 2.0에서 소개되었습니다.

조건부 목록 이해

주어진 목록 이해 하나 이상을 추가 할 수 있습니다 if 조건 값을 필터링 할 수 있습니다.

[<expression> for <element> in <iterable> if <condition>]

<iterable><element> 에 대해; <condition>True 평가되면 <expression> (일반적으로 <element> 의 함수)을 반환 된 목록에 추가합니다.


예를 들어, 정수 시퀀스에서 짝수를 추출하는 데 사용할 수 있습니다.

[x for x in range(10) if x % 2 == 0]
# Out: [0, 2, 4, 6, 8]

라이브 데모

위의 코드는 다음과 같습니다.

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

print(even_numbers)
# Out: [0, 2, 4, 6, 8]

또한, [e for x in y if c] 식인 [e for x in y if c] 의 조건부 목록 이해 [e for x in y if c] (여기서 ecx 표현식입니다.)는 list(filter(lambda x: c, map(lambda x: e, y))) .

동일한 결과를 제공 했음에도 불구하고 이전 예제가 후자보다 거의 2 배 빠르다는 사실에주의하십시오. 호기심이 많은 사람들에게 이것은 이유에 대한 좋은 설명입니다.


이것은 list comprehension의 <expression> 부분에 사용할 수있는 ... if ... else ... 조건식 ( 3 진 표현식 이라고도 함)과는 매우 다른 점에 유의하십시오. 다음 예제를 고려하십시오.

[x if x % 2 == 0 else None for x in range(10)]
# Out: [0, None, 2, None, 4, None, 6, None, 8, None]

라이브 데모

조건식은 필터가 아니라 목록 항목에 사용할 값을 결정하는 연산자입니다.

<value-if-condition-is-true> if <condition> else <value-if-condition-is-false>

다른 연산자와 결합하면 더 명확 해집니다.

[2 * (x if x % 2 == 0 else -1) + 1 for x in range(10)]
# Out: [1, -1, 5, -1, 9, -1, 13, -1, 17, -1]

라이브 데모

Python 2.7을 사용하는 경우, xrange 문서에 설명 된 것처럼 xrange 가 여러 가지 이유로 range 보다 우수 할 수 있습니다.

[2 * (x if x % 2 == 0 else -1) + 1 for x in xrange(10)]
# Out: [1, -1, 5, -1, 9, -1, 13, -1, 17, -1]

위의 코드는 다음과 같습니다.

numbers = []
for x in range(10):
    if x % 2 == 0:
        temp = x
    else:
        temp = -1
    numbers.append(2 * temp + 1)
print(numbers)
# Out: [1, -1, 5, -1, 9, -1, 13, -1, 17, -1]

하나는 삼항 표현과 결합 할 if 조건을. 삼항 연산자는 필터링 된 결과에 대해 작업합니다.

[x if x > 2 else '*' for x in range(10) if x % 2 == 0]
# Out: ['*', '*', 4, 6, 8]

삼원 연산자만으로는 같은 결과를 얻을 수 없었습니다.

[x if (x > 2 and x % 2 == 0) else '*' for x in range(10)]
# Out:['*', '*', '*', '*', 4, '*', 6, '*', 8, '*']

또한 : 조건부 목록 내포에 대한 충분한 대안을 제공하는 필터 .

중첩 루프가 포함 된 목록 이해

List Comprehensions 은 중첩 된 for 루프를 사용할 수 있습니다. 목록 내포 내에서 임의의 수의 중첩 된 for 루프를 코딩 할 수 있으며 for 루프마다 선택적 if 관련 if 테스트가있을 수 있습니다. 그렇게 할 때 for 구조의 순서는 일련의 중첩 for 문을 작성할 때와 같은 순서입니다. list comprehensions의 일반적인 구조는 다음과 같습니다.

[ expression for target1 in iterable1 [if condition1]
             for target2 in iterable2 [if condition2]...
             for targetN in iterableN [if conditionN] ]

예를 들어 다음 for 코드는 for 문을 여러 개 사용하여 목록을 병합합니다.

data = [[1, 2], [3, 4], [5, 6]]
output = []
for each_list in data:
    for element in each_list:
        output.append(element)
print(output)
# Out: [1, 2, 3, 4, 5, 6]

동등하게 복수와 지능형리스트로 쓸 수 for 구조 :

data = [[1, 2], [3, 4], [5, 6]]
output = [element for each_list in data for element in each_list]
print(output)
# Out: [1, 2, 3, 4, 5, 6]

라이브 데모

확장 형식과 목록 이해 모두에서 외부 루프 (첫 번째 문)가 먼저옵니다.


더 소형화 될뿐만 아니라, 중첩 된 이해력도 상당히 빠릅니다.

In [1]: data = [[1,2],[3,4],[5,6]]
In [2]: def f():
   ...:     output=[]
   ...:     for each_list in data:
   ...:         for element in each_list:
   ...:             output.append(element)
   ...:     return output
In [3]: timeit f()
1000000 loops, best of 3: 1.37 µs per loop
In [4]: timeit [inner for outer in data for inner in outer]
1000000 loops, best of 3: 632 ns per loop

위의 함수 호출에 대한 오버 헤드는 약 140ns 입니다.


인라인 if 의 유사 중첩되고, 처음 이후 어느 위치에서 발생할 수있는 for :

data = [[1], [2, 3], [4, 5]]
output = [element for each_list in data
                if len(each_list) == 2
                for element in each_list
                if element != 5]
print(output)
# Out: [2, 3, 4]

라이브 데모

그러나 가독성을 위해 기존 for 루프를 사용하는 것을 고려해야합니다. 중첩이 2 단계 이상 깊거나 이해력의 논리가 너무 복잡 할 때 특히 그렇습니다. 여러 개의 중첩 루프 목록 이해가 오류가 발생하거나 예상치 못한 결과가 발생할 수 있습니다.

리팩토링 필터 및 목록 내재에 매핑

filter 또는 map 기능은 종종 목록 내포 로 대체되어야합니다. 귀도 반 로섬 (Guido Van Rossum) 은 2005 년 공개 서한에서 이를 잘 설명합니다.

filter(P, S) 는 거의 항상 [x for x in S if P(x)] 로 명확하게 표시되며, 가장 일반적인 용도는 x==42 와 같은 비교어 인 조건부를 포함한다는 큰 이점이 있습니다. 람다는 독자를 위해 훨씬 더 많은 노력을 요구합니다 (람다는 목록 이해보다 느립니다). map(F, S)[F(x) for x in S] 됩니다. 물론 많은 경우에 대신 생성기 표현식을 사용할 수 있습니다.

다음 코드 행은 " pythonic이 아닌 "것으로 간주되어 많은 python linters에서 오류를 발생시킵니다.

filter(lambda x: x % 2 == 0, range(10)) # even numbers < 10
map(lambda x: 2*x, range(10)) # multiply each number by two
reduce(lambda x,y: x+y, range(10)) # sum of all elements in list

우리는 이전의 인용에서 배운 것을 가지고 가서, 우리는 이러한 분해 할 수 filtermap 자신의 상응하는 지능형리스트로 표현; 또한 각각에서 람다 함수를 제거하여 코드를 프로세스에서 더 읽기 쉽게 만들어줍니다.

# Filter:
# P(x) = x % 2 == 0
# S = range(10)
[x for x in range(10) if x % 2 == 0]

# Map
# F(x) = 2*x
# S = range(10)
[2*x for x in range(10)]

연쇄 기능을 처리 할 때 가독성이 더욱 분명 해집니다. 가독성으로 인해 하나의지도 또는 필터 함수의 결과가 다음 결과로 전달되어야합니다. 단순한 경우에는 단일 목록 이해로 대체 할 수 있습니다. 또한, 우리는 목록 작성에서 프로세스의 결과가 무엇인지, 체인 된 맵 및 필터 프로세스에 대해 추론 할 때 더 많은인지 적로드가있는 곳을 쉽게 알 수 있습니다.

# Map & Filter
filtered = filter(lambda x: x % 2 == 0, range(10))
results = map(lambda x: 2*x, filtered)

# List comprehension
results = [2*x for x in range(10) if x % 2 == 0]

리팩토링 - 빠른 참조

  • 지도

    map(F, S) == [F(x) for x in S]
    
  • 필터

    filter(P, S) == [x for x in S if P(x)]
    

여기서 FP 는 각각 입력 값을 변환하고 bool 반환하는 함수입니다.

중첩 목록 이해

중첩 된 목록 내포는 중첩 루프가있는 목록 내포와 달리 목록 이해 내에서 목록 내포입니다. 초기 표현식은 다른 목록 이해력을 포함하여 임의의 표현식이 될 수 있습니다.

#List Comprehension with nested loop
[x + y for x in [1, 2, 3] for y in [3, 4, 5]]
#Out: [4, 5, 6, 5, 6, 7, 6, 7, 8]

#Nested List Comprehension
[[x + y for x in [1, 2, 3]] for y in [3, 4, 5]]
#Out: [[4, 5, 6], [5, 6, 7], [6, 7, 8]]

중첩 된 예제는 다음과 같습니다.

l = []
for y in [3, 4, 5]:
    temp = []
    for x in [1, 2, 3]:
        temp.append(x + y)
    l.append(temp)

중첩 된 이해력을 사용하여 행렬을 조 변경하는 한 가지 예입니다.

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

[[row[i] for row in matrix] for i in range(len(matrix))]
# [[1, 4, 7], [2, 5, 8], [3, 6, 9]]

중첩 된 for 루프와 마찬가지로 중첩이 될 수있는 방법에 제한이 없습니다.

[[[i + j + k for k in 'cd'] for j in 'ab'] for i in '12']
# Out: [[['1ac', '1ad'], ['1bc', '1bd']], [['2ac', '2ad'], ['2bc', '2bd']]]

목록 내에서 동시에 두 개 이상의 목록 반복

list comprehension 에서 두 개 이상의리스트를 동시에 반복하기 위해, zip() 을 다음과 같이 사용할 수 있습니다 :

>>> list_1 = [1, 2, 3 , 4]
>>> list_2 = ['a', 'b', 'c', 'd']
>>> list_3 = ['6', '7', '8', '9']

# Two lists
>>> [(i, j) for i, j in zip(list_1, list_2)]
[(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd')]

# Three lists
>>> [(i, j, k) for i, j, k in zip(list_1, list_2, list_3)]
[(1, 'a', '6'), (2, 'b', '7'), (3, 'c', '8'), (4, 'd', '9')]

# so on ...


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow