5. 자료 구조
************

이 장에서는 여러분이 이미 배운 것들을 좀 더 자세히 설명하고, 몇 가지
새로운 것들을 덧붙입니다.


5.1. 리스트 더 보기
===================

리스트 자료 형은 몇 가지 메서드들을 더 갖고 있습니다. 이것들이 리스트
객체의 모든 메서드 들입니다:

list.append(x)

   Add an item to the end of the list; equivalent to "a[len(a):] =
   [x]".

list.extend(L)

   Extend the list by appending all the items in the given list;
   equivalent to "a[len(a):] = L".

list.insert(i, x)

   주어진 위치에 항목을 삽입합니다. 첫 번째 인자는 삽입되는 요소가 갖
   게 될 인덱스입니다. 그래서 "a.insert(0, x)" 는 리스트의 처음에 삽입
   하고, "a.insert(len(a), x)" 는 "a.append(x)" 와 동등합니다.

list.remove(x)

   Remove the first item from the list whose value is *x*. It is an
   error if there is no such item.

list.pop([i])

   리스트에서 주어진 위치에 있는 항목을 삭제하고, 그 항목을 돌려줍니다
   . 인덱스를 지정하지 않으면, "a.pop()" 은 리스트의 마지막 항목을 삭
   제하고 돌려줍니다. (메서드 시그니처에서 *i* 를 둘러싼 꺾쇠괄호는 파
   라미터가 선택적임을 나타냅니다. 그 위치에 꺾쇠괄호를 입력해야 한다
   는 뜻이 아닙니다. 이 표기법은 파이썬 라이브러리 레퍼런스에서 지주
   등장합니다.)

list.index(x)

   Return the index in the list of the first item whose value is *x*.
   It is an error if there is no such item.

list.count(x)

   리스트에서 *x* 가 등장하는 횟수를 돌려줍니다.

list.sort(cmp=None, key=None, reverse=False)

   리스트의 항목들을 제자리에서 정렬합니다 (인자들은 정렬 커스터마이제
   이션에 사용될 수 있습니다. 설명은 "sorted()" 를 보세요).

list.reverse()

   Reverse the elements of the list, in place.

리스트 메서드 대부분을 사용하는 예:

   >>> a = [66.25, 333, 333, 1, 1234.5]
   >>> print a.count(333), a.count(66.25), a.count('x')
   2 1 0
   >>> a.insert(2, -1)
   >>> a.append(333)
   >>> a
   [66.25, 333, -1, 333, 1, 1234.5, 333]
   >>> a.index(333)
   1
   >>> a.remove(333)
   >>> a
   [66.25, -1, 333, 1, 1234.5, 333]
   >>> a.reverse()
   >>> a
   [333, 1234.5, 1, 333, -1, 66.25]
   >>> a.sort()
   >>> a
   [-1, 1, 66.25, 333, 333, 1234.5]
   >>> a.pop()
   1234.5
   >>> a
   [-1, 1, 66.25, 333, 333]

You might have noticed that methods like "insert", "remove" or "sort"
that only modify the list have no return value printed -- they return
the default "None".  This is a design principle for all mutable data
structures in Python.


5.1.1. 리스트를 스택으로 사용하기
---------------------------------

리스트 메서드들은 리스트를 스택으로 사용하기 쉽게 만드는데, 마지막에
넣은 요소가 처음으로 꺼내지는 요소입니다 ("last-in, first-out"). 스택
의 꼭대기에 항목을 넣으려면 "append()" 를 사용하세요. 스택의 꼭대기에
서 값을 꺼내려면 명시적인 인덱스 없이 "pop()" 을 사용하세요. 예를 들어
:

   >>> stack = [3, 4, 5]
   >>> stack.append(6)
   >>> stack.append(7)
   >>> stack
   [3, 4, 5, 6, 7]
   >>> stack.pop()
   7
   >>> stack
   [3, 4, 5, 6]
   >>> stack.pop()
   6
   >>> stack.pop()
   5
   >>> stack
   [3, 4]


5.1.2. 리스트를 큐로 사용하기
-----------------------------

리스트를 큐로 사용하는 것도 가능한데, 처음으로 넣은 요소가 처음으로 꺼
내지는 요소입니다 ("first-in, first-out"); 하지만, 리스트는 이 목적에
는 효율적이지 않습니다. 리스트의 끝에 덧붙이거나, 끝에서 꺼내는 것은
빠르지만, 리스트의 머리에 덧붙이거나 머리에서 꺼내는 것은 느립니다 (다
른 요소들을 모두 한 칸씩 이동시켜야 하기 때문입니다).

큐를 구현하려면, 양 끝에서의 덧붙이기와 꺼내기가 모두 빠르도록 설계된
"collections.deque" 를 사용하세요. 예를 들어:

   >>> from collections import deque
   >>> queue = deque(["Eric", "John", "Michael"])
   >>> queue.append("Terry")           # Terry arrives
   >>> queue.append("Graham")          # Graham arrives
   >>> queue.popleft()                 # The first to arrive now leaves
   'Eric'
   >>> queue.popleft()                 # The second to arrive now leaves
   'John'
   >>> queue                           # Remaining queue in order of arrival
   deque(['Michael', 'Terry', 'Graham'])


5.1.3. Functional Programming Tools
-----------------------------------

There are three built-in functions that are very useful when used with
lists: "filter()", "map()", and "reduce()".

"filter(function, sequence)" returns a sequence consisting of those
items from the sequence for which "function(item)" is true. If
*sequence* is a "str", "unicode" or "tuple", the result will be of the
same type; otherwise, it is always a "list".  For example, to compute
a sequence of numbers divisible by 3 or 5:

   >>> def f(x): return x % 3 == 0 or x % 5 == 0
   ...
   >>> filter(f, range(2, 25))
   [3, 5, 6, 9, 10, 12, 15, 18, 20, 21, 24]

"map(function, sequence)" calls "function(item)" for each of the
sequence's items and returns a list of the return values.  For
example, to compute some cubes:

   >>> def cube(x): return x*x*x
   ...
   >>> map(cube, range(1, 11))
   [1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]

More than one sequence may be passed; the function must then have as
many arguments as there are sequences and is called with the
corresponding item from each sequence (or "None" if some sequence is
shorter than another).  For example:

   >>> seq = range(8)
   >>> def add(x, y): return x+y
   ...
   >>> map(add, seq, seq)
   [0, 2, 4, 6, 8, 10, 12, 14]

"reduce(function, sequence)" returns a single value constructed by
calling the binary function *function* on the first two items of the
sequence, then on the result and the next item, and so on.  For
example, to compute the sum of the numbers 1 through 10:

   >>> def add(x,y): return x+y
   ...
   >>> reduce(add, range(1, 11))
   55

If there's only one item in the sequence, its value is returned; if
the sequence is empty, an exception is raised.

A third argument can be passed to indicate the starting value.  In
this case the starting value is returned for an empty sequence, and
the function is first applied to the starting value and the first
sequence item, then to the result and the next item, and so on.  For
example,

   >>> def sum(seq):
   ...     def add(x,y): return x+y
   ...     return reduce(add, seq, 0)
   ...
   >>> sum(range(1, 11))
   55
   >>> sum([])
   0

Don't use this example's definition of "sum()": since summing numbers
is such a common need, a built-in function "sum(sequence)" is already
provided, and works exactly like this.


5.1.4. 리스트 컴프리헨션
------------------------

리스트 컴프리헨션은 리스트를 만드는 간결한 방법을 제공합니다. 흔한 용
도는, 각 요소가 다른 시퀀스나 이터러블의 멤버들에 어떤 연산을 적용한
결과인 리스트를 만들거나, 어떤 조건을 만족하는 요소들로 구성된 서브 시
퀀스를 만드는 것입니다.

예를 들어, 제곱수의 리스트를 만들고 싶다고 가정하자, 이런 식입니다:

   >>> squares = []
   >>> for x in range(10):
   ...     squares.append(x**2)
   ...
   >>> squares
   [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

We can obtain the same result with:

   squares = [x**2 for x in range(10)]

This is also equivalent to "squares = map(lambda x: x**2, range(10))",
but it's more concise and readable.

리스트 컴프리헨션은 표현식과 그 뒤를 따르는 "for" 절과 없거나 여러 개
의 "for" 나 "if" 절들을 감싸는 꺾쇠괄호로 구성됩니다. 그 결과는 새 리
스트인데, "for" 와 "if" 절의 문맥에서 표현식의 값을 구해서 만들어집니
다. 예를 들어, 이 리스트 컴프리헨션은 두 리스트의 요소들을 서로 같지
않은 것끼리 결합합니다:

   >>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
   [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

and it's equivalent to:

>>> combs = []
>>> for x in [1,2,3]:
...     for y in [3,1,4]:
...         if x != y:
...             combs.append((x, y))
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]

두 코드 조각에서 "for" 와 "if" 문의 순서가 같음에 유의하세요.

표현식이 튜플이면 (즉 앞의 예에서 "(x, y)"), 반드시 괄호로 둘러싸야 합
니다.

   >>> vec = [-4, -2, 0, 2, 4]
   >>> # create a new list with the values doubled
   >>> [x*2 for x in vec]
   [-8, -4, 0, 4, 8]
   >>> # filter the list to exclude negative numbers
   >>> [x for x in vec if x >= 0]
   [0, 2, 4]
   >>> # apply a function to all the elements
   >>> [abs(x) for x in vec]
   [4, 2, 0, 2, 4]
   >>> # call a method on each element
   >>> freshfruit = ['  banana', '  loganberry ', 'passion fruit  ']
   >>> [weapon.strip() for weapon in freshfruit]
   ['banana', 'loganberry', 'passion fruit']
   >>> # create a list of 2-tuples like (number, square)
   >>> [(x, x**2) for x in range(6)]
   [(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
   >>> # the tuple must be parenthesized, otherwise an error is raised
   >>> [x, x**2 for x in range(6)]
     File "<stdin>", line 1, in <module>
       [x, x**2 for x in range(6)]
                  ^
   SyntaxError: invalid syntax
   >>> # flatten a list using a listcomp with two 'for'
   >>> vec = [[1,2,3], [4,5,6], [7,8,9]]
   >>> [num for elem in vec for num in elem]
   [1, 2, 3, 4, 5, 6, 7, 8, 9]

리스트 컴프리헨션은 복잡한 표현식과 중첩된 함수들을 포함할 수 있습니다
:

   >>> from math import pi
   >>> [str(round(pi, i)) for i in range(1, 6)]
   ['3.1', '3.14', '3.142', '3.1416', '3.14159']


5.1.4.1. 중첩된 리스트 컴프리헨션
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

리스트 컴프리헨션의 첫 표현식으로 임의의 표현식이 올 수 있는데, 다른
리스트 컴프리헨션도 가능합니다.

다음과 같은 길이가 4인 리스트 3개의 리스트로 구현된 3x4 행렬의 예를 봅
시다:

   >>> matrix = [
   ...     [1, 2, 3, 4],
   ...     [5, 6, 7, 8],
   ...     [9, 10, 11, 12],
   ... ]

다음 리스트 컴프리헨션은 행과 열을 전치 시킵니다:

   >>> [[row[i] for row in matrix] for i in range(4)]
   [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

앞절에서 보았듯이, 중첩된 리스트 컴프리헨션은 뒤따르는 "for" 의 문맥에
서 값이 구해집니다. 그래서 이 예는 다음과 동등합니다:

   >>> transposed = []
   >>> for i in range(4):
   ...     transposed.append([row[i] for row in matrix])
   ...
   >>> transposed
   [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

이것은 다시 다음과 같습니다:

   >>> transposed = []
   >>> for i in range(4):
   ...     # the following 3 lines implement the nested listcomp
   ...     transposed_row = []
   ...     for row in matrix:
   ...         transposed_row.append(row[i])
   ...     transposed.append(transposed_row)
   ...
   >>> transposed
   [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]

실제 세상에서는, 복잡한 흐름문보다 내장 함수들을 선호해야 합니다. 이
경우에는 "zip()" 함수가 제 역할을 할 수 있습니다:

   >>> zip(*matrix)
   [(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12)]

이 줄에 나오는 에스터리스크에 대한 자세한 내용은 인자 목록 언 패킹 을
보세요.


5.2. "del" 문
=============

리스트에서 값 대신에 인덱스를 사용해서 항목을 삭제하는 방법이 있습니다
: "del" 문입니다. 이것은 값을 돌려주는 "pop()" 메서드와 다릅니다.
"del" 문은 리스트에서 슬라이스를 삭제하거나 전체 리스트를 비우는 데도
사용될 수 있습니다 (앞에서 빈 리스트를 슬라이스에 대입해서 했던 일입니
다). 예를 들어:

   >>> a = [-1, 1, 66.25, 333, 333, 1234.5]
   >>> del a[0]
   >>> a
   [1, 66.25, 333, 333, 1234.5]
   >>> del a[2:4]
   >>> a
   [1, 66.25, 1234.5]
   >>> del a[:]
   >>> a
   []

"del" 는 변 자체를 삭제하는데에도 사용될 수 있습니다:

   >>> del a

이후에 이름 "a" 를 참조하는 것은 에러입니다 (적어도 다른 값이 새로 대
입되기 전까지). 뒤에서 "del" 의 다른 용도를 보게 됩니다.


5.3. 튜플과 시퀀스
==================

리스트와 문자열이 인덱싱과 슬라이싱 연산과 같은 많은 성질을 공유함을
보았습니다. 이것들은 *시퀀스* 자료 형의 두 가지 예입니다 (Sequence
Types --- str, unicode, list, tuple, bytearray, buffer, xrange 를 보세
요). 파이썬은 진화하는 언어이기 때문에, 다른 시퀀스 자료형이 추가될 수
도 있습니다. 다른 표준 시퀀스 자료 형이 있습니다: *튜플* 입니다.

튜플은 쉼표로 구분되는 여러 값으로 구성됩니다. 예를 들어:

   >>> t = 12345, 54321, 'hello!'
   >>> t[0]
   12345
   >>> t
   (12345, 54321, 'hello!')
   >>> # Tuples may be nested:
   ... u = t, (1, 2, 3, 4, 5)
   >>> u
   ((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))
   >>> # Tuples are immutable:
   ... t[0] = 88888
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: 'tuple' object does not support item assignment
   >>> # but they can contain mutable objects:
   ... v = ([1, 2, 3], [3, 2, 1])
   >>> v
   ([1, 2, 3], [3, 2, 1])

여러분이 보듯이, 출력되는 튜플은 항상 괄호로 둘러싸입니다, 그래서 중첩
된 튜플이 올바르게 해석됩니다; 종종 괄호가 필요하기는 하지만 (튜플이
더 큰 표현식의 일부일 때), 둘러싼 괄호와 함께 또는 없이 입력될 수 있습
니다. 튜플의 개별 항목에 대입하는 것은 가능하지 않지만, 리스트 같은 가
변 객체를 포함하는 튜플을 만들 수는 있습니다.

튜플이 리스트처럼 보인다 하더라도, 이것들은 다른 상황에서 다른 목적으
로 사용됩니다. 튜플은 *불변* 이고, 보통 이질적인 요소들의 시퀀스를 포
함합니다. 요소들은 언 패킹 (이 섹션의 뒤에 나온다) 이나 인덱싱 (또는 "
네임드 튜플" 의 경우는 어트리뷰트로도) 으로 액세스합니다. 리스트는 *가
변* 이고, 요소들은 보통 등질 적이고 리스트에 대한 이터레이션으로 액세
스 됩니다.

특별한 문제는 비었거나 하나의 항목을 갖는 튜플을 만드는 것입니다: 이
경우를 수용하기 위해 문법은 추가적인 예외 사항을 갖고 있습니다. 빈 튜
플은 빈 괄호 쌍으로 만들어집니다; 하나의 항목으로 구성된 튜플은 값 뒤
에 쉼표를 붙여서 만듭니다 (값 하나를 괄호로 둘러싸기만 하는 것으로는
충분하지 않습니다). 추합니다, 하지만 효과적입니다. 예를 들어:

   >>> empty = ()
   >>> singleton = 'hello',    # <-- note trailing comma
   >>> len(empty)
   0
   >>> len(singleton)
   1
   >>> singleton
   ('hello',)

문장 "t = 12345, 54321, 'hello!'" 는 *튜플 패킹* 의 예입니다: 값
"12345", "54321", "'hello!'" 는 함께 튜플로 패킹 됩니다. 반대 연산 또
한 가능합니다:

   >>> x, y, z = t

This is called, appropriately enough, *sequence unpacking* and works
for any sequence on the right-hand side.  Sequence unpacking requires
the list of variables on the left to have the same number of elements
as the length of the sequence.  Note that multiple assignment is
really just a combination of tuple packing and sequence unpacking.


5.4. 집합
=========

파이썬은 *집합* 을 위한 자료 형도 포함합니다. 집합은 중복되는 요소가
없는 순서 없는 컬렉션입니다. 기본적인 용도는 멤버십 검사와 중복 엔트리
제거입니다. 집합 객체는 합집합, 교집합, 차집합, 대칭 차집합과 같은 수
학적인 연산들도 지원합니다.

집합을 만들 때는 중괄호나 "set()" 함수를 사용할 수 있습니다. 주의사항:
빈 집합을 만들려면 "set()" 을 사용해야 합니다. "{}" 가 아닙니다; 후자
는 빈 딕셔너리를 만드는데, 다음 섹션에서 다룹니다.

여기 간략한 실연이 있습니다:

   >>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
   >>> fruit = set(basket)               # create a set without duplicates
   >>> fruit
   set(['orange', 'pear', 'apple', 'banana'])
   >>> 'orange' in fruit                 # fast membership testing
   True
   >>> 'crabgrass' in fruit
   False

   >>> # Demonstrate set operations on unique letters from two words
   ...
   >>> a = set('abracadabra')
   >>> b = set('alacazam')
   >>> a                                  # unique letters in a
   set(['a', 'r', 'b', 'c', 'd'])
   >>> a - b                              # letters in a but not in b
   set(['r', 'd', 'b'])
   >>> a | b                              # letters in either a or b
   set(['a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'])
   >>> a & b                              # letters in both a and b
   set(['a', 'c'])
   >>> a ^ b                              # letters in a or b but not both
   set(['r', 'd', 'b', 'm', 'z', 'l'])

리스트 컴프리헨션 과 유사하게, 집합 컴프리헨션도 지원됩니다:

   >>> a = {x for x in 'abracadabra' if x not in 'abc'}
   >>> a
   set(['r', 'd'])


5.5. 딕셔너리
=============

파이썬에 내장된 또 하나의 쓸모있는 자료 형은 *딕셔너리* 입니다 (매핑
형 --- dict 를 보세요). 딕셔너리는 종종 다른 언어들에서 "연관 메모리
(associative memories)" 나 "연관 배열(associative arrays)" 의 형태로
발견됩니다. 숫자들로 인덱싱되는 시퀀스와 달리, 딕셔너리는 *키* 로 인덱
싱되는데, 모든 불변형을 사용할 수 있습니다; 문자열과 숫자들은 항상 키
가 될 수 있습니다. 튜플이 문자열, 숫자, 튜플들만 포함하면, 키로 사용될
수 있습니다; 튜플이 직접적이나 간접적으로 가변 객체를 포함하면, 키로
사용될 수 없습니다. 리스트는 키로 사용할 수 없는데, 리스트는 인덱스 대
입, 슬라이스 대입, "append()" 나 "extend()" 같은 메서드들로 값이 수정
될 수 있기 때문입니다.

딕셔너리를 (한 딕셔너리 안에서) 키가 중복되지 않는다는 제약 조건을 가
진 *키: 값* 쌍의 순서 없는 집합으로 생각하는 것이 최선입니다. 중괄호
쌍은 빈 딕셔너리를 만듭니다: "{}". 중괄호 안에 쉼표로 분리된 키:값 쌍
들의 목록을 넣으면, 딕셔너리에 초기 키:값 쌍들을 제공합니다; 이것이 딕
셔너리가 출력되는 방식이기도 합니다.

딕셔너리의 주 연산은 값을 키와 함께 저장하고 주어진 키로 값을 추출하는
것입니다. "del" 로 키:값 쌍을 삭제하는 것도 가능합니다. 이미 사용하고
있는 키로 저장하면, 그 키로 저장된 예전 값은 잊힙니다. 존재하지 않는
키로 값을 추출하는 것은 에러입니다.

The "keys()" method of a dictionary object returns a list of all the
keys used in the dictionary, in arbitrary order (if you want it
sorted, just apply the "sorted()" function to it).  To check whether a
single key is in the dictionary, use the "in" keyword.

여기에 딕셔너리를 사용하는 조그마한 예가 있습니다:

   >>> tel = {'jack': 4098, 'sape': 4139}
   >>> tel['guido'] = 4127
   >>> tel
   {'sape': 4139, 'guido': 4127, 'jack': 4098}
   >>> tel['jack']
   4098
   >>> del tel['sape']
   >>> tel['irv'] = 4127
   >>> tel
   {'guido': 4127, 'irv': 4127, 'jack': 4098}
   >>> tel.keys()
   ['guido', 'irv', 'jack']
   >>> 'guido' in tel
   True

"dict()" 생성자는 키-값 쌍들의 시퀀스로 부터 직접 딕셔너리를 구성합니
다.

   >>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
   {'sape': 4139, 'jack': 4098, 'guido': 4127}

이에 더해, 딕셔너리 컴프리헨션은 임의의 키와 값 표현식들로 부터 딕셔너
리를 만드는데 사용될 수 있습니다:

   >>> {x: x**2 for x in (2, 4, 6)}
   {2: 4, 4: 16, 6: 36}

키가 간단한 문자열일 때, 때로 키워드 인자들을 사용해서 쌍을 지정하기가
쉽습니다:

   >>> dict(sape=4139, guido=4127, jack=4098)
   {'sape': 4139, 'jack': 4098, 'guido': 4127}


5.6. 루프 테크닉
================

시퀀스를 루핑할 때, "enumerate()" 함수를 사용하면 위치 인덱스와 대응하
는 값을 동시에 얻을 수 있습니다.

   >>> for i, v in enumerate(['tic', 'tac', 'toe']):
   ...     print i, v
   ...
   0 tic
   1 tac
   2 toe

둘이나 그 이상의 시퀀스를 동시에 루핑하려면, "zip()" 함수로 엔트리들의
쌍을 만들 수 있습니다.

   >>> questions = ['name', 'quest', 'favorite color']
   >>> answers = ['lancelot', 'the holy grail', 'blue']
   >>> for q, a in zip(questions, answers):
   ...     print 'What is your {0}?  It is {1}.'.format(q, a)
   ...
   What is your name?  It is lancelot.
   What is your quest?  It is the holy grail.
   What is your favorite color?  It is blue.

시퀀스를 거꾸로 루핑하려면, 먼저 정방향으로 시퀀스를 지정한 다음에
"reversed()" 함수를 호출하세요.

   >>> for i in reversed(xrange(1,10,2)):
   ...     print i
   ...
   9
   7
   5
   3
   1

정렬된 순서로 시퀀스를 루핑하려면, "sorted()" 함수를 사용해서 소스를
변경하지 않고도 정렬된 새 리스트를 받을 수 있습니다.

   >>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
   >>> for f in sorted(set(basket)):
   ...     print f
   ...
   apple
   banana
   orange
   pear

When looping through dictionaries, the key and corresponding value can
be retrieved at the same time using the "iteritems()" method.

   >>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
   >>> for k, v in knights.iteritems():
   ...     print k, v
   ...
   gallahad the pure
   robin the brave

때로 루프를 돌고 있는 리스트를 변경하고픈 유혹을 느낍니다; 하지만, 종
종, 대신 새 리스트를 만드는 것이 더 간단하고 더 안전합니다.

   >>> import math
   >>> raw_data = [56.2, float('NaN'), 51.7, 55.3, 52.5, float('NaN'), 47.8]
   >>> filtered_data = []
   >>> for value in raw_data:
   ...     if not math.isnan(value):
   ...         filtered_data.append(value)
   ...
   >>> filtered_data
   [56.2, 51.7, 55.3, 52.5, 47.8]


5.7. 조건 더 보기
=================

"while" 과 "if" 문에서 사용되는 조건에는 비교뿐만 아니라 모든 연산자를
사용할 수 있습니다.

비교 연산자 "in" 과 "not in" 은 값이 시퀀스에 있는지 (없는지) 검사합니
다. 연산자 "is" 와 "is not" 은 두 객체가 진짜로 같은 객체인지 비교합니
다; 이것은 리스트와 같은 가변 객체에서만 의미가 있습니다. 모든 비교 연
산자들은 같은 우선순위를 갖는데, 모든 산술 연산자들보다 낮습니다.

비교는 연쇄할 수 있습니다. 예를 들어, "a < b == c" 는, "a" 가 "b" 보다
작고, 동시에 "b" 가 "c" 와 같은지 검사합니다.

비교는 논리 연산자 "and" 와 "or" 를 사용해서 결합할 수 있고, 비교의 결
과는 (또는 그 밖의 모든 논리 표현식은) "not" 으로 부정될 수 있습니다.
이것들은 비교 연산자보다 낮은 우선순위를 갖습니다. 이것 간에는 "not"
이 가장 높은 우선순위를 갖고, "or" 가 가장 낮습니다. 그래서 "A and not
B or C" 는 "(A and (not B)) or C" 와 동등합니다. 여느 때처럼, 원하는
조합을 표현하기 위해 괄호를 사용할 수 있습니다.

논리 연산자 "and" 와 "or" 는 소위 *단락-회로(short-circuit)* 연산자입
니다: 인자들은 왼쪽에서 오른쪽으로 값이 구해지고, 결과가 결정되자마자
값 구하기는 중단됩니다. 예를 들어, "A" 와 "C" 가 참이고 "B" 가 거짓이
면, "A and B and C" 는 표현식 "C" 의 값을 구하지 않습니다. 논리값이 아
닌 일반 값으로 사용될 때, 단락-회로 연산자의 반환 값은 마지막으로 값이
구해진 인자입니다.

비교의 결과나 다른 논리 표현식의 결과를 변수에 대입할 수 있습니다. 예
를 들어,

   >>> string1, string2, string3 = '', 'Trondheim', 'Hammer Dance'
   >>> non_null = string1 or string2 or string3
   >>> non_null
   'Trondheim'

파이썬에서, C와는 달리, 대입은 표현식 안에 등장할 수 없습니다. C 프로
그래머들이 이 문제로 투덜거리지만, C 프로그램에서 흔히 마주치는 부류의
문제들을 회피하도록 합니다: "==" 를 사용할 표현식에 "=" 를 입력하는 실
수.


5.8. 시퀀스와 다른 형들을 비교하기
==================================

Sequence objects may be compared to other objects with the same
sequence type. The comparison uses *lexicographical* ordering: first
the first two items are compared, and if they differ this determines
the outcome of the comparison; if they are equal, the next two items
are compared, and so on, until either sequence is exhausted. If two
items to be compared are themselves sequences of the same type, the
lexicographical comparison is carried out recursively.  If all items
of two sequences compare equal, the sequences are considered equal. If
one sequence is an initial sub-sequence of the other, the shorter
sequence is the smaller (lesser) one.  Lexicographical ordering for
strings uses the ASCII ordering for individual characters.  Some
examples of comparisons between sequences of the same type:

   (1, 2, 3)              < (1, 2, 4)
   [1, 2, 3]              < [1, 2, 4]
   'ABC' < 'C' < 'Pascal' < 'Python'
   (1, 2, 3, 4)           < (1, 2, 4)
   (1, 2)                 < (1, 2, -1)
   (1, 2, 3)             == (1.0, 2.0, 3.0)
   (1, 2, ('aa', 'ab'))   < (1, 2, ('abc', 'a'), 4)

Note that comparing objects of different types is legal.  The outcome
is deterministic but arbitrary: the types are ordered by their name.
Thus, a list is always smaller than a string, a string is always
smaller than a tuple, etc. [1] Mixed numeric types are compared
according to their numeric value, so 0 equals 0.0, etc.

-[ 각주 ]-

[1] The rules for comparing objects of different types should not
    be relied upon; they may change in a future version of the
    language.
