본문 바로가기
프로그래밍/Python

파이썬 문법 7 - 자료 구조

by pentode 2018. 4. 9.

앞에서 리스트, 튜플, 셋과 같은 파이썬에서 특징적인 자료형에 대해서 알아 보았습니다. "Python 문법 2 - 식별자, 데이터 타입, 형변환, 연산자"를 참조하세요. 

 

이번에는 이미 알아보았던 자료형들에 대해서 몇가지 새로운 사항에 대해서 알아보겠습니다.

 

 

1. 리스트의 메소드들

 

list.append( x ) : 리스트의 끝에 항목을 추가하십시오. ( a[len(a):] = [x] )

list.extend( iterable ) : iterable의 모든 항목을 추가하여 목록을 확장 해당합니다. ( a[len(a):] = iterable )

list.insert( i, x ) : 주어진 위치에 항목을 삽입합니다. 첫 번째 인수는 삽입하기 전에 요소의 인덱스이므로 a.insert(0, x)는 목록의 앞에 삽입 합니다. 그리고 a.insert(len(a), x)와 a.append(x)는 동일하게 끝에 추가 합니다.

list.remove( x ) : 리스트에서 값이 X인 첫 번째 항목을 제거 합니다. 해당 항목이 없으면 오류입니다.

list.pop( [ i ] ) : 리스트 내의 지정된 위치에 있는 아이템을 삭제하고, 그것을 반환합니다. 인덱스를 지정하지 않으면 a.pop()은  리스트의 마지막 항목을 제거하고 반환합니다. ( 메소드 인자에서 i 를 둘러싼 대괄호는 매개 변수가 선택적이라는 것을 뜻합니다. 그 위치에 대괄호를 입력해야하는 것은 아닙니다.이 표기법은 Python Library Reference에서 자주 볼 수 있습니다.)

list.clear( ) : 리스트에서 모든 항목을 제거합니다.( del a[:] )

list.index( x [, start [, end ] ] ) : 리스트에서 값이 x 인 첫 번째 항목의 인덱스를 반환합니다. 인덱스는 0부터 시작 합니다. 그러한 항목이 없는 경우 ValueError 를 발생시킵니다. 선택적 인수 start 와 end 는 특정 하위 시퀀스로 검색을 제한하는데 사용됩니다. 반환된 인덱스는 전체 시퀀스의 시작 부분을 기준으로 계산 됩니다.

list.count( x ) : x가 리스트에 나타나는 회수를 반환합니다.

list.sort( key = None , reverse = False ) : 리스트의 항목을 정렬합니다.

list.reverse( ) : 리스트의 요소들의 순서를 뒤집습니다.

list.copy( ) : 리스트의 얕은(shallow) 카피를 돌려줍니다. a[:]와 동일합니다.

 

※참고

얕은 복사(shallow copy) : 데이터는 그대로 있고, 주소가 복사되어 집니다. 하나의 데이터를 여러 변수가 가리키고 있는 상황이 됩니다.

깊은 복사(deep copy) : 데이터까지 복사되어 새로운 데이터가 생성되어 집니다. 깊은 복사는 다음과 같이 할 수 있습니다.

 

>>> import copy
>>> foo = copy.deepcopy(list)

 

리스트의 insert, remove, sort 와 같은 메소드를 수행하면 리스트 자체의 값이 바뀌고 어떠한 값도 반환되지 않습니다. 이것이 파이썬에서 변경 가능한(mutable) 자료형에서의 동작 방식입니다.

 

 

1.1. 리스트를 스택(stack)처럼 사용하기

 

리스트를 스택(stack) 처럼 사용하는 것은 간단합니다. 스택의 동작 방식은 "last-in, first-out" 입니다. 마지막에 들어간 것이 먼저 나오게 됩니다. 리스트의 마지막에 값을 추가하기 위해서 list.append(x) 를 사용합니다. 마지막의 값을 삭제하고 꺼내기 위해서 list.pop() 을 사용합니다.

 

 

1.2. 리스트를 큐(queue)처럼 사용하기

 

리스트를 큐(queue)처럼 사용하는것도 가능합니다. 큐(queue)의 동작 방식은 "first-in, first-out" 입니다. 제일 먼저 들어간 것이 제일 먼저 나오게 됩니다. 큐에 넣기 위해서 list.append(x) 를 사용합니다. 큐에서 꺼내기 위해서 list.pop(0) 를 사용합니다.

 

리스트를 큐로 사용하는것은 효율적이지 못합니다. 시작 부분에서 pop 하는 것이 늦기 때문입니다. 큐를 구현하려면 collections.deque 를 사용하는것이 좋습니다. (deque데크로 읽습니다.) deque는 큐의 양쪽 끝에서 빠르게 값을 넣고 뺄 수 있도록 디자인 되었습니다.

 

>>> from collections import deque
>>> queue = deque(["Eric", "John", "Michael"])
>>> queue.append("Terry")
>>> queue.append("Graham")
>>> queue.popleft()
    'Eric'
>>> queue.popleft()
    'John'
>>> queue
    deque(['Michael', 'Terry', 'Graham'])
>>> queue.pop()
    'Graham'

 

 

1.3. List Comprehensions

 

이건 뭐라고 번역을 해야 할지 모르겠군요. 그냥  List Comprehansion 이라고 적겠습니다. List Comprehansion 은 리스트를 만드는 간결한 방법을 제공합니다. 리스트를 왜 만들까요? 리스트는 순차적이고, 변경 가능한 자료 구조입니다.

 

프로그램 중에는 이런 형식의 데이터를 많이 사용합니다. 프로그램 작업이 이런 데이터에 어떤 작업을 가해서 결과 리스트를 만드는 것이거나, 원본 리스트 중에 조건에 맞는 일부를 뽑아 새로운 리스트를 만드는 작업이 많습니다. 이런 작업을 간단하게 코딩할 수 있도로 해주는게 List Comprehension 이라는 것입니다.

 

예를 보겠습니다. 0 ~ 9까지 제곱수의 리스트를 만드는 방법입니다. 일반적인 for 문을 사용했습니다.

 

>>> squares = []
>>> for x in range(10):
        squares.append(x**2)

>>> squares
    [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

 

람다(lambda) 를 사용하면 아래 처럼 할 수 있습니다.

 

squares = list(map(lambda x: x**2, range(10)))

 

List Comprehension을 사용하면 좀더 간단한 모양이 됩니다.

 

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

 

좀더 복잡한 예를 보겠습니다.

 

리스트 [1,2,3]에 대해 각각이 리스트 [3,1,4]의 각각에 매칭되어 두 개의 요소를 가지는 튜플(tuple)을 생성합니다. 총 아홉개가 생성될 수 있는데, 두 개의 값이 같지 않은 것만 뽑아냅니다.

 

※ 튜플은 순서가 있고, 읽기전용인 데이터로 소괄호()로 둘러쌉니다.

 

일반적인 for 루프로 구현하면 아래와 같습니다.

 

>>> 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)]​

 

List Comprehension 을 사용하면 아래처럼 할 수 있습니다.

 

>>> [(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)]

 

for문은 중첩될 수 있고, 맨뒤에 나오는 조건식(if x != y) 은 옵션 입니다.

 

 

1.4. 중첩된 List Comprehension

 

List Comprehension에서 첫 번째 나오는 초기 표현식(출력되는 표현식)은 다른 List Comprehension을 포함한 임의의 표현식이 가능합니다.

 

>>> 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]]

 

 

2. del 문장

 

리스트에서 아이템을 삭제하는데 list.remove(x)를 사용할 수 있습니다. 이것은 값이 x 와 일치하는 아이템을 리스트에서 삭제합니다. 다른 방법은 list.pop(i) 를 사용해서 i 번째 아이템을 삭제할 수 있습니다.

 

리스트에서 아이템을 삭제하는 다른 방법은 del 문장이 있습니다. 이것은 인덱스를 이용해서 특정 위치의 아이템을 삭제합니다. pop 과는 다르게 반환하는것이 없습니다. 하나의 아이템을 삭제 할수도 있고, 특정 범위의 아이템들을 삭제할수도 있습니다.

 

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

 

변수 전체를 삭제 할 수도 있습니다.

 

>>> del a

 

 

3. 조건에 대한 추가 정보

 

while문과 if문에 사용되는 조건에는 비교 연사자외에 어떤 연산자라도 사용될 수 있습니다. 연산의 결과 값이 0, False, null, 공백 이면 거짓으로 나머지는 참으로 판단됩니다.

 

비교 연산자 in 과 not in 은 시퀀스 내에 값이 있는지 없는지를 판단합니다. 연산자 is 와 is not 은 두 객체가 정말 같은 객체인지 비교합니다. 이것은 리스트와 같은 변경 가능한 객체에 대해서만 의미가 있습니다.

 

>>> a = [1,2,3]
>>> b = [1,2,3]
>>> a == b
    True
>>> a is b
    False
>>>

 

모든 비교연산자는 동일한 우선 순위를 가지며, 모든 숫자 연산자보다 우선 순위가 낮습니다.

 

비교는 연쇄적으로 일어날 수 있습니다. 예로 a < b == c는 a가 b 보다 작고 b는 c와 같을 때 참입니다. 다른 언어라면 아마도 (a < b) and (b == c) 형식으로 적었을 것입니다.

 

비교 연산자는 and 와 or 로 묶여질 수 있습니다. 그리고 비교 또는 불리언 연산의 결과를 not 연산자로 뒤집을 수 있습니다. 이 연산자는 비교연산자 보다 우선 순위가 낮습니다. not 이 가장 우선순위가 높고, and, or 으로 우선순위를 가집니다. 즉, A and not B or C 는 (A and (nto B)) or C 와 같습니다.

 

불리언 연산자 and 와 or는 short-circuit 연산자로도 불립니다. 쇼터서킷 연산자는 왼쪽에서 오른쪽으로 평가가되고 값이 결정되면 나머지는 평가하지 않고 건너뜁니다. 예로 (A > B) or (B > C) 연산에서 A > B 가 참이면 이 전체 연산은 항상 참이기 때문에 뒤의 B > C는 평가되지 않고 넘어갑니다.

 

불리언 연산자는 할당에도 사용할 수 있습니다.

 

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

 

위의 예에서 보면 string1 은 값이 없으므로 False이고, 두 번째 string2 는 값이 있으므로 True 이므로 여기까지만 평가됩니다. 그래서 'Trondheim' 이 대입됩니다.

 

 

4. 시퀀스 끼리의 비교와 다른 유형의 비교

 

시퀀스 끼리의 비교는 동일한 시퀀스 타입끼리 비교가 가능합니다. 동작방식은 개개의 요소를 순차적으로 사전순(lexicographical ordering)으로 비교합니다.

 

객체가 적절한 비교 방법을 가지고 있는 경우에는 다른 타입의 객체를 < 또는 > 로 비교할 수 있습니다. 예로, 서로 다른 숫자 타입인 0과 0.0은 숫자값을 비교하여 같다는 결과가 나옵니다. 이렇게 비교할 수 없는 것들은 임의의 순서를 지정하지 않고 인터프리터가 TypeError 를 발생시킵니다.

 

>>> a = 0
>>> b = 0.0
>>> c = 'test'
>>> a > b
    False
>>> a == b
    True
>>> a == c
    False
>>> a < c
    Traceback (most recent call last):
        File "<pyshell#11>", line 1, in <module>
            a < c
    TypeError: '<' not supported between instances of 'int' and 'str'
>>>

 

출처 : https://docs.python.org/3/tutorial/datastructures.html

반응형