2020년 8월 26일
[파이썬] 배열 형태의 자료구조
I. 튜플(tuple)과 네임드 튜플(named tuple)
가. 튜플(tuple)
- 튜플은 변경 불가 클래스로, 객체 생성 후 원소를 변경, 삭제, 추가할 수 없고 색인 연산을 통해 조회만 가능
- [예제] 튜플 (tuple)
t = tuple((1, 2, 3, 2, 1)) # 튜플 객체를 리터럴로 표기(쉼표로 구분) print(t.count(2)) # 원소 값(2)의 개수를 count print(t.index(3)) # 인덱스 정보의 원소 조회 [결과] 2 2
나. 네임드 튜플(named tuple)
- 각 원소에 이름을 붙이고 이름으로 원소에 접근
- [예제] collections 모듈을 사용한 네임드 튜플 (named tuple)
import collections as cols # 여러 원소를 가진 collections 모듈 import NamedTupleClass = cols.namedtuple("NamedTuple", "x, y, z") # 새로운 네임드 튜플 클래스 생성 nt = NamedTupleClass(1, 2, 3) # 생성한 네임드 튜플 클래스로 오브젝트 생성 print(nt) print(nt.y) [결과] NamedTuple(x=1, y=2, z=3) 2
- [예제] typing 모듈을 사용한 네임드 튜플 (named tuple)
import typing class Point(typing.NamedTuple) : x : int y : int z : int p = Point(1, 2, 3) print(p) print(p.z) # 이름으로 값 조회 print(p[1]) # 배열 순서로 값 조회 [결과] Point(x=1, y=2, z=3) 3 2
II. 리스트(list)
- 리스트는 object 클래스를 자료형으로 인식하여 파이썬 객체를 원소로 가질 수 있으며, 변경, 삭제, 추가 가능
- 리스트로 객체를 만드는 방법은 대괄호(“[“, “]”)를 사용하거나 생성자를 사용
- [예제] 리스트
list1 = [1, 2, 3] list2 = [4, 5] list1.append(list2) # 기존 객체에 리스트를 원소로 추가 print("append 적용: ",list1) list1.pop() # 마지막 원소를 삭제 print("pop 적용: ", list1) list1.remove(2) # 원소 중 특정 값을 찾아 삭제 print("remove 적용: ", list1) list1.extend(list2) # 기존 리스트에 리스트의 원소를 추가(append와 다름) print("extend 적용: ", list1) list1 = list1 + list2 # 덧셈 연산 사용 시 새로운 리스트 생성 print("덧셈연산 적용:", list1) list1.clear() print("clear 적용: ", list1) list1.insert(0, 1) # 특정 인덱스 위치에 원소를 삽입 list1.insert(0, 2) print("insert 적용: ", list1) [결과] append 적용: [1, 2, 3, [4, 5]] pop 적용: [1, 2, 3] remove 적용: [1, 3] extend 적용: [1, 3, 4, 5] 덧셈연산 적용: [1, 3, 4, 5, 4, 5] clear 적용: [] insert 적용: [2, 1]
III. 얕은 복사(swallow copy)와 깊은 복사(deep copy)
- 파이썬에서는 기본적으로 얕은 복사(swallow copy를 지원
- 중첩 리스트나 딕셔너리 복사를 위해서는 깊은 복사(deep copy) 사용 필요
- [예제] 리스트 복사
list1 = [1, 2, 3, 4] list2 = list1 print("list1 ID: ", id(list1), ", list2 ID : ", id(list2)) # id 값이 동일하므로 얕은 복사 수행 확인 list3 = list1.copy() print("list1 ID: ", id(list1), ", list3 ID : ", id(list3)) # id 값이 다르므로 새로운 객체 생성 확인 newList = [5, 6, 7] list1.append(newList) # 중첩 리스트 만들기 위해 [5, 6, 7] 리스트를 원소로 append print("append 적용: ", list1) list1Copy = list1.copy() print("copy 적용: ", list1Copy) list1Copy[4][0]= 99 # 마지막 원소의 첫 번째 원소 갱신 print("list1: ", list1) # 일반적인 복사(Copy) 시 중첩된 리스트는 복사하지 않음 print("list1Copy: ", list1Copy) print("list1의 4번째 원소(중첩리스트) ID: ", id(list1[4]), "list1Copy의 4번째 원소(중첩리스트) ID", id(list1Copy[4])) # 중첩 리스트를 모두 새로 만들기 위해 깊은 복사(deep copy) 함수 사용 import copy list1Deepcopy = copy.deepcopy(list1) print("list1의 4번째 원소(중첩리스트) ID: ", id(list1[4]), "list1Deepcopy 4번째 원소(중첩리스트) ID", id(list1Deepcopy[4])) list1Deepcopy[4][1] = 88 print("list1: ", list1) # 깊은 복사(deep copy) 시 중첩된 리스트도 새로 복사하여 생성 print("list1Deepcopy: ", list1Deepcopy) [결과] list1 ID: 20957704 , list2 ID : 20957704 list1 ID: 20957704 , list3 ID : 25715272 append 적용: [1, 2, 3, 4, [5, 6, 7]] copy 적용: [1, 2, 3, 4, [5, 6, 7]] list1: [1, 2, 3, 4, [99, 6, 7]] list1Copy: [1, 2, 3, 4, [99, 6, 7]] list1의 4번째 원소(중첩리스트) ID: 25716040 list1Copy의 4번째 원소(중첩리스트) ID 25716040 list1의 4번째 원소(중첩리스트) ID: 25716040 list1Deepcopy 4번째 원소(중첩리스트) ID 26469576 list1: [1, 2, 3, 4, [99, 6, 7]] list1Deepcopy: [1, 2, 3, 4, [99, 88, 7]]
IV. Queue 자료구조
- Queue 메소드 정의 시 객체 상태 확인 empty 함수와 저장된 원소의 상태 확인 getQueue 함수를 작성
- 원소 정보를 보여줄 때는 다른 리스트 객체를 만들어 반환(원본은 공유하지 않아야 함)
- 그 다음 Queue 저장소에 원소를 넣는 put 함수와 원소를 꺼내는 get 함수를 작성
class Queue : def __init__(self) : self._list = [] # 여러 원소 저장을 위한 빈 리스트 할당 def empty(self) : return True if len(self._list) == 0 else False # 큐에 원소가 없는 상태 확인 def get(self) : # 원소를 꺼낼 때는 항상 마지막 원소를 꺼냄 if len(self._list) == 0 : return 0 else : return self._list.pop(-1) def put(self, value) : # 원소 저장 시 항상 0 번 째에 값 저장 return self._list.insert(0, value) def getQueue(self) : # 원소 정보를 보여줄 때는 다른 리스트 객체를 만들어 반환 return self._list.copy() q = Queue() print("최초 큐 생성") print("빈 큐인지 여부: ", q.empty()) print("빈 큐에서 원소 꺼내면: ", q.get()) q.put(10) print("10 저장 후: ", q.getQueue()) q.put(20) print("20 저장 후: ", q.getQueue()) q.get() print("원소 하나 꺼낸 후: ", q.getQueue()) q.put(30) print("30 저장 후: ", q.getQueue()) q.get() print("원소 하나 꺼낸 후: ", q.getQueue()) [결과] 초 큐 생성 빈 큐인지 여부: True 빈 큐에서 원소 꺼내면: 0 10 저장 후: [10] 20 저장 후: [20, 10] 원소 하나 꺼낸 후: [20] 30 저장 후: [30, 20] 원소 하나 꺼낸 후: [30]
[참고]
- 잇플, “한 권으로 개발자가 원하던 파이썬 심화 A to Z”, 2019.11