컨테이너

변수는 데이터 하나를 담을 수 있다.

이와 다르게 컨테이너는 여러개의 데이터를 담을 수 있는 객체로 데이터 종류에 무관하게 자료형을 저장할 수 있다.

컨테이너는 데이터를 저장하는 데 순서가 있거나(ordered) 순서가 없는 것(unordered)으로 구분한다.

순서가 있고, 인덱스로 접근 가능한 것을 시퀀스형이라고 하고 순서가 없는 (인덱스로 접근 불가능한) 것을 비시퀀스형이라고 한다.

컨테이너의 요소를 수정, 추가, 삭제할 수 있는 것은 가변형(mutable), 요소를 수정할 수 없는 것은 불변형(immutable)으로 나눌 수 있다.

 

 

 

순서가 있는 시퀀스형 (ordered) 불변형 (immutable) 튜플
레인지
가변형 (mutable) 리스트
순서가 없는 비시퀀스형 (unordered) 세트
딕셔너리

 

 

 

시퀀스형

리스트(list)

[] 대괄호나 list()으로 생성할 수 있다. 여러개의 데이터를 순서가 있는 구조로 저장한다. 

순서가 있는 시퀀스로 index를 통해 접근하며 인덱스는 0부터 시작한다.

리스트에는 자료형의 종류에 관계없이 데이터를 저장할 수 있고, 리스트 안에 리스트를 넣을 수도 있다.

가변형으로 리스트 생성이후 내용 변경이 가능하다.

 

 

리스트명 = [요소1, 요소2 ...]

list_name = [1,'리스트요소',['hello',2,3]]

위에서 생성한 리스트에서 '리스트요소'라는 데이터는 인덱스 1번으로 list_name[1] 이다.

 

 

list_name[1] = '수정'

리스트는 가변형이기때문에 요소를 변경할 수도 있다.

 

 

print(list_name) #[1, '수정', ['hello', 2, 3]]

변경된 리스트를 출력해서 확인할 수 있따.

 

 

print(list_name[2][1]) #2

리스트안에 리스트가 있을 때는 인덱스를 위와같이 이어서 사용할 수 있다.

list_name[2]의 리스트에서 index 1번 값을 출력하니, 내부 리스트의 두번째 값인 2가 나온다.

 

 

print(list_name[2][-1]) #3

-1은 끝에서 첫번째 요소를 의미한다. 리스트안의 index 2번인 리스트안에서 끝의 값인 3이 출력된다.

 

 

print(list_name[-1][0][0])

list_name 리스트에서 끝에서 첫번째의 요소인 리스트를 선택하고, 그 안에서 0번째 인덱스가 선택된다. 

이것은 요소 'hello'를 의미한다. 여기서 인덱스 [0]은 h를 의미한다.

문장에서 h는 인덱스0, e는 1.... 이 된다.

 

 

print(type(list_name)) #class 'list'

type()으로 자료형을 확인할 수 있다. 

 

 

 

 

 

 

튜플(tuple)

소괄호()나 tuple()으로 생성하고 수정불가능한 시퀀스형이다. 순서가 있는 시퀀스형이기 때문에 인덱스로 접근 가능하다.

값을 변경하려고 하면 에러가 뜬다. 

tu=(1,2,3,)
print(type(tu)) #class 'tuple'
print(tu[1]) #2

 

 

튜플에서 항목을 저장할 때 쉼표(,)로 이어준다. 튜플 생성시에는 단일 항목으로 구성된 튜플을 만들 때에도 쉼표를 붙여야 하는 것을 주의해야 한다.

tu=(1,)

 

여러항목을 저장할 때는 끝에 쉼표를 붙여주거나, 붙이지 않아도 된다.

 

 

튜플 대입 (tuple assignment)

x,y =1,2

이와같이 데이터를 변수에 한번에 저장할 수 있다. 

 

x, y =(1,2)

사실 이것은 내부적으로 튜플을 이용해서 값이 처리된 것이다.

 

 

 

레인지 range(start, end, step)

숫자의 시퀀스를 나타내기 위한 것으로 주로 반복문과 함께 사용된다.

 

 

ragne(n)

0부터 n-1까지 숫자 시퀀스

range(a,b)

a부터 b-1까지 숫자 시퀀스

range(a,b,s)

a부터 b-1까지 s만큼 증가(step)시킨 숫자 시퀀스

 

print(list(range(5))) #[0,1,2,3,4]

range(5) 는 range(0,5)와 동일하고 0, 1, 2, 3, 4 를 의미한다. 끝의 값은 포함되지 않는다.

range(1,5,2) 은 1, 3이 된다. 2만큼 증가시켰고 5는 포함하지 않는다.

range 값을 확인하기 위해서는 List로 만들어서 출력하면 된다.

 

 

print(list(range(5,1,-1)))  #[5,4,3,2]

range(5,1,-1) 은 5부터 시작하고 1은 포함되지 않는다.

step에서 음수값은 역순을 의미하여 거꾸로 출력해서 결과는 5,4,3,2 이다.

 

print(list(range(6,1,-2))) #[6,4,2]

range(6,1,-2) 은 6부터 1까지 역순으로 2칸씩이며 6,4,2 이다.

 

print(list(range(6,1,1))) #[]

range(6,1,1) 은 6부터 1까지인데 거꾸로가 아니기 때문에 아무런 시퀀스가 없다.

 

 

 

시퀀스 슬라이싱 [start:end:step] - 리스트, 튜플, 레인지, 문자열

인덱스[]와 : 를 이용해서 시퀀스를 특정 단위로, 여러간격으로 슬라이싱하여 잘라낼 수 있다. 

start부터 end까지 이며 end는 포함되지 않는다.

 

 

print([1,2,3,4,5][1:4]) #[2,3,4]
print((1,2,3,4,5)[:2]) #(1,2)
print((1,2,3,4,5)[2:]) #(3,4,5)
print([1,2,3,4,5][4:0:-1]) #[5,4,3,2]
print(list(range(1,6))[1:5:2]) #[2,4]

[1,2,3,4,5] 리스트에서 [1:4] 이라면 index 1번인 index 4번까지를 말하며 끝은 포함되지 않는다. 2,3,4 이다.

[:2] 는 0부터 2까지로 인덱스 0, 1만 지정하여 값은 1, 2 이다.

[2:] 은 2부터 끝까지이다.

step의 마이너스값은 역순을 말한다.

 

 

 

 

print('abcdd' [::]) #abcde
print('abcde'[1:4:2]) #bd
print('abced'[:3]) #abc
print('abced'[2:]) #ced
print('abced'[::-1]) #edcba

문자열도 인덱스가 0부터 시작하며 동일하다.

[::]은 처음부터 끝까지이며 [::-1]은 처음부터 끝까지 거꾸로 나열하는 것이다.

 

 

 

arr = [1,2,3,4,5]
copy = arr #arr을 저장하고 있는 주소값을 copy에 저장
arr[0]=10
print(arr) #[10,2,3,4,5]
print(copy) #[10,2,3,4,5]

arr = [1,2,3,4,5]
copy = arr[:] #arr 데이터 값을 copy에 저장
arr[0]=10
print(arr) #[10,2,3,4,5]
print(copy) #[1,2,3,4,5]

 

[:] 없이 대입연산자로 대입을 하면 주소값이 저장되기 때문에 이 경우에는 arr과 copy 가 동일한 주소값을 가지고 있어서 하나의 데이터가 바뀌면 연결된 다른 데이터도 바뀌게 된다.

값만을 복사해서 저장하고 싶을 때는 [:] 으로 하면 전체를 저장할 수 있다.

원본과 다른 새로운 데이터를 만들기 위해서는 [:] 을 써서 데이터를 가져와야 한다.

 

 

 

 

비시퀀스형

세트(set)

{} 중괄호나 set()으로 생성한다. 

중복되는 요소없이 순서에 관계없는 데이터 묶음이다.

중복되는 요소가 있으면 하나만 저장하고 순서가 없기 때문에 인덱스를 이용해서 접근 불가능하다.

수학의 집합과 동일하며 합집합, 교집합, 차집합같은 집합연산이 가능하다.

가변형으로 요소를 추가, 변경, 삭제가 가능한다.

 

print({1,2,2,2,3}) #{1,2,3}
print(type({1,2,3})) #class 'set'

 

비어있는 set을 만들기 위해서는 set()을 사용해야 한다.

{} 으로 빈 중괄호로 만들면 dictionary 타입이 된다.

blank = {}
print(type(blank)) #class 'dict'
blank_set = set()
print(type(blank_set)) #class 'set'

 

 

set을 활용하여 다른 컨테이너의 중복된 값을 제거 할 수 있다. 

my_list=[1,2,2,3]
print(set(my_list)) #{1,2,3}

중복이 있는 리스트를 set로 변경하여 중복값을 제거하였다. 이때 set은 비시퀀스형이기 때문에 실행할 때마다 순서가 달라지기 때문에 순서가 중요한 경우에는 주의해야 한다.

 

 

셋(set) 연산자

| 합집합

& 교집합

- 차집합

^ 대칭차집합

 

여집합 연산은 없다.

 

a = {1,2,3}
b = {1,2,'hello'}

print(a|b) #{1,2,3,'hello'}
print(a&b) #{1,2}
print(a-b) #{3}
print(a^b) #{3,'hello'}

합집합은 중복 제외한 모든 요소를 나타내고 교집합은 공통 요소만을 나타낸다.

차집합 a-b은 a에는 있지만 b에는 없는 요소만 나타낸다. a요소중에 a,b 교집합을 제외한 것이다.

대칭차집합은 합집합에서 교집합을 제외한 것으로 전체 요소에서 겹치는 요소만 제외한 것이다. a만 가지고 있는, b만 가지고 있는 요소인 3과 hello가 출력된다.

 

 

 

딕셔너리 (dictionary)

{} 중괄호나 dict()으로 생성한다.

{key : value, key : value ... }

dict(key=value, key=value...)

key(키)-value(값) 쌍으로 이루어진 자료형으로 python 3.7부터 순서가 있는 ordered 구조이다.

입력한 순서대로 저장되지만 인덱스로 접근할 수 없기 때문에 시퀀스형이 아니다.

key 키는 변경이 불가능한 데이터(immutable)로 string, integer, float, boolean, tuple, range이 가능하며 value는 어떠한 형태든 관계없다.

 

a = {}
print(type(a)) #class 'dict'

{} 으로 빈 딕셔너리 생성가능하다.

 

 

a = {'a': 123 , 'b' : 'hello', 'c' : [1,2,3]}
print(a) #{'a': 123, 'b': 'hello', 'c': [1, 2, 3]}
print(a['c']) #[1, 2, 3]

key값을 print 하면 value 값이 출력된다.

 

 

b=dict(a=123,b='hello',list=[1,2,3])
print(b) #{'a': 123, 'b': 'hello', 'c': [1, 2, 3]}

dict()으로 사용하는 것은 key=value 형태로 저장한다. key값은 자동으로 문자열로 저장된다.

 

 

a = {'a': 123 , 'b' : 'hello', 'c' : [1,2,3]}

print(a.keys()) #dict_keys(['a', 'b', 'c'])

.keys() 으로 key값만 가져올 수 있다.

 

for el in a.keys() :
    print(a[el])
    
for el in a :
    print(a[el])

for문으로 하나씩 value 값을 꺼내올 수도 있다.

 

 

print(a.values()) #dict_values([123, 'hello', [1, 2, 3]])

.values() 으로 value값을 한번에 가져올 수 있다.

 

 

for key, value in a.items():
	print(f'{key} : {value}')

.items()는 key, value 모두 가져오기 때문에 위와 같이 각각을 가져올 수 있다.

딕셔너리는 시퀀스가 아니지만 .keys()으로 시퀀스처럼 사용할 수 있게 된다.

 

 

 

print(a.get('a')) #123
print(a['a']) #123

print(a.get('d')) #None
print(a['d']) #KeyError

딕셔너리 a의 key값이 a인 값을 가져오기 위해 get함수를 쓰는 방법과 직접 가져오는 방법을 비교해 본다.

해당하는 키값이 있을 때는 차이가 없이 value값을 가져오고 출력한다. 

하지만 해당하는 키값일 존재하지 않을 때 차이가 있다. 직접 딕셔너리명['키값'] 으로 가져올 때 존재하는 키값이면 KeyError가 발생한다.

get 함수를 이용하면 키값이 존재하지 않을 때 에러대신 None으로 결과가 출력된다.