pass05wk-2: 파이썬의 자료형 (2)
1. 강의영상
2. Imports
3. tuple
A. 리스트 vs 튜플
- 공통점: (1) 컨테이너형타입이라는 점, 그리고 (2) 연산 및 인덱싱을 하는 방법은 리스트와 같음 - 차이점1: [] 대신에 ()를 사용한다. - 차이점2: 불변형이다. (원소의 값을 바꿀 수 없음) - 차이점3: 하나의 원소를 선언할 때는 (1,)와 같이 해야 한다. - 차이점4: 의미가 명확할때는 튜플의 ()를 생략가능하다.
- 컨테이너형이라는 것이 무슨의미?
a=(4,6,'pencil', 3.2+4.6j, [3,4])type(a[2])str
type(a[3])complex
- 연산의 유사성
(1,2) + (3,4,5)(1, 2, 3, 4, 5)
(1,2) * 2(1, 2, 1, 2)
- 인덱싱의 유사성
tpl = (11,21,31)
tpl[1:](21, 31)
- 차이점2: 불변형이라는 것은 무슨의미?
a[2] = 'Pencil'TypeError: 'tuple' object does not support item assignment
참고로 a를 튜플이 아니라 리스트로 선언하면 값이 잘 바뀐다.
a=[4,6,'pencil', 3.2+4.6j, [3,4]]a[2]'pencil'
a[2]='Pencil'a[4, 6, 'Pencil', (3.2+4.6j), [3, 4]]
- 차이점3: 하나의 원소로 이루어진 튜플을 만들때는 쉼표를 붙여야 함.
[1]+[2,3,4][1, 2, 3, 4]
(1,)+(2,3,4)(1, 2, 3, 4)
- 차이점4: 의미가 명확할때 튜플의 괄호는 생략가능하다. (이게 중요합니다)
a=1,2
a(1, 2)
의미가 명확할때 생략해야함
1,2 + 3,4,5 (1, 5, 4, 5)
(1,2) + (3,4,5) (1, 2, 3, 4, 5)
B. 선언
- 소괄호를 이용
a=(1,2,3)
a(1, 2, 3)
type(a)tuple
- 생략가능하다는 점이 포인트
a=1,2,3
a(1, 2, 3)
type(a)tuple
- 원소가 하나인 튜플을 만들고 싶다면?
a=(1,)
a(1,)
C. 연산
- 리스트와 동일
(1,2)+(3,4,5)(1, 2, 3, 4, 5)
(1,2)*2(1, 2, 1, 2)
D. 인덱싱
- 리스트와 동일
a=(1,2,3,-4,-5)
a(1, 2, 3, -4, -5)
a[-1]-5
a[-3:](3, -4, -5)
E. 슬기로운 튜플사용 (\(\star\))
# 예제 – 여러변수를 동시에 출력하고 싶을 경우 (다중출력?)
변수를 아래와 같이 선언하였다고 하자.
a=1
b=2
c=3선언된 값을 확인하려면?
a1
b2
c3
튜플을 이용하면?
a,b,c # 괄호하나 생략하는것이 이렇게 편하다..(1, 2, 3)
#
# 예제2 – 다중할당1 (여러개의 변수를 동시에 선언하고 싶을 경우)
아래와 같이 =를 5번 쓰면 5개의 변수를 선언할 수 있다.
name = 'Tom'
age = 20
sex = 'M'
height = 180
weight = 70튜플을 이용하면 좀더 간단히 하나의 = 로도 아래와 같이 선언할 수 있다.
name, age, sex, height, weight = 'Tom', 20, 'M', 180, 70 # 다중할당#
# 예제2 – 다중할당2, 위도와 경도
coor = (37,127) # 서울
coor(37, 127)
lat, long = coor # 다중할당lat 37
long 127
#
# 잠깐만 – 다중할당은 꼭 튜플에서만 가능한가?
그건 아니다…
[x,y,z] = [1,2,3]
x,y,z # 다중출력 (1, 2, 3)
[x,y] = 'hi'
x,y ('h', 'i')
튜플과 같이 사용하면 가독성이 극대화 (그래서 다중할당은 거의 튜플과 세트로 사용함)
x,y,z = 1,2,3
x,y,z # 다중출력 (1, 2, 3)
x,y = 'hi'
x,y ('h', 'i')
#
# 예제 – 임시변수 사용없이 두 변수의 값을 교환
a=10
b=20a,b(10, 20)
a,b = b,a a,b(20, 10)
#
# 예제 – for문과 튜플
lst = [['guebin', 202112345, 'M'],
['iu',202254321, 'F'],
['hodong', 202011223, 'M']]
lst[['guebin', 202112345, 'M'],
['iu', 202254321, 'F'],
['hodong', 202011223, 'M']]
lst[0]['guebin', 202112345, 'M']
for name,studentid,sex in lst:
print(name,sex)guebin M
iu F
hodong M
#
# 예제 – for문과 튜플, dummy variable _
for name,studentid,sex in lst:
print(studentid)202112345
202254321
202011223
for _,studentid,_ in lst:
print(studentid)202112345
202254321
202011223
for _,_,sex in lst:
print(sex)M
F
M
for name,_,sex in lst:
print(name,sex)guebin M
iu F
hodong M
for name,_,_ in lst:
print(name)guebin
iu
hodong
#
# 예제 – 튜플과 언패킹연산자 *
아래와 같이 관심없는것 모두를 other라는 이름으로 받을 수 있음
for name,*other in lst:
print(name,other)guebin [202112345, 'M']
iu [202254321, 'F']
hodong [202011223, 'M']
*의 동작을 더 세심히 살펴보자.
head, body, *tail = range(1,11)
head, body, tail(1, 2, [3, 4, 5, 6, 7, 8, 9, 10])
head1,head2, *body, tail1,tail2,tail3 = range(1,11)
head1,head2, body, tail1,tail2,tail3 (1, 2, [3, 4, 5, 6, 7], 8, 9, 10)
*head, body, tail = range(1,11)
head, body, tail([1, 2, 3, 4, 5, 6, 7, 8], 9, 10)
(관찰)
그러고 보니까..
[*head, body, tail] = [1,2,3,4,5,6,7,8,9,10]
[head, body, tail] = [[1,2,3,4,5,6,7,8],9,10] 이렇다는 거잖아?
*를 붙이면 1차원 자료구조가 풀린다..?
[1,2,[1,2,3]][1, 2, [1, 2, 3]]
[1,2,*[1,2,3]][1, 2, 1, 2, 3]
- 단독사용은 불가능
*[1,2,3]SyntaxError: can't use starred expression here (386627056.py, line 1)
F. 튜플을 왜 쓸까? – 제 생각..
- 질문: 리스트를 쓰지 않고 왜 튜플을 써야하나?
- 답변1: (책의 설명)
- 초보적인 설명: 실수방지
- 더 정확한 설명: 빠르다, 여러사람과 작업하기 유리하다, 깊은복사/얕은복사시 원하지 않는 오류 (side effect 이라고 함) 방지
- 답변2: 괄호를 생략할 수 있기 때문에, 리스트 말고 튜플을 쓰면 편함.
- 소괄호의 생략 + 언패킹 \(\Rightarrow\) 엄청난 가독성.
- 컴공과 사람들 의견: 튜플 + 언패킹 \(\Rightarrow\) 엄청난 가독성 \(\Rightarrow\) 충격 \(\Rightarrow\) “파이썬 편하더라고요..”
- 근본적인 의문: 파이썬을 처음 만들때 리스트에 괄호를 생략하는 기능을 추가했으면 편했잖아?
- 저의 설명: 리스트=신라면, 튜플=라면사리 같은 느낌으로 이해하면 된다. 불변형(튜플)은 기능제한이 있는데, 가변형(리스트)는 기능이 풍부하다. 대신에, 가변형은 느리고 무겁다.
- 기능적으로만 보면, 신라면이 있으면 스프를 버리고 라면사리를 얻을 수 있음, 그래서 라면사리는 필요없음.
- 그런데 신라면에서 스프를 버려서 라면사리를 항상 얻는다면, 비효율적임.
- 우리가 원하는게 (1) 원소를 벡터형태로 모은뒤 (2) 벡터자체를 출력해보고 (3) 각 원소를
sort하고 (4) 원소를 추가append하고 (5) 원소를 삭제remove하는 것 일수도 있음. 그렇지만 진짜 단순하게 (1),(2) 만 원할수도있음. - 단순히 (1)-(2)의 목적으로 리스트를 사용하는건 비효율적이니까 불변형인 튜플을 만듦. (1)-(2)를 사용함에 있어서 편리성을 극대화 하기위해 괄호도 생략하게 해줌.
def mycal(a,b):
return a+b, a-b, a*b, a/b # 여러개의 값을 리턴하는듯 보임 -> 사실은 길이가 4인 튜플 1개를 리턴mycal(1,2)(3, -1, 2, 0.5)
_,_,mul,_ = mycal(1,2)mul2
G. 연습문제들
# 문제. 길이가 1인 튜플을 만들어 자신의 학번을 저장하라. 길이가 1인 튜플을 만들어 자신의 영문이름을 저장하라. 두 튜플을 + 연산자로 합쳐아래와 같은 출력결과를 얻어라. 최종 결과는 예를들면 아래와 같아야 한다.
('2021-43052', 'GuebinChoi')('2021-43052', 'GuebinChoi')
(풀이)
sid = ('2021-43052',)
name = ('GuebinChoi',)sid+name('2021-43052', 'GuebinChoi')
파이썬프로그래밍 수강생. 아래는 파이썬프로그래밍 수강생들의 학번, 이름, 출석점수, 과제점수, 중간고사점수, 기말고사점수를 저장한 중첩리스트이다.
lst = [['2021-43052', 'GuebinChoi', 5, 10, 20, 25],
['2019-12342', 'Heung-min Son', 10, 15, 30, 15],
['2018-32234', 'hynn', 7, 20, 30, 15],
['2022-42323', 'Minji', 8, 20, 20, 35],
['2023-55342', 'Hanni', 7, 20, 30, 35],
['2022-46624', 'Danielle', 3, 15, 30, 40],
['2022-11239', 'Haerin', 10, 20, 30, 40],
['2022-32114', 'Hyein', 10, 20, 20, 35]]
lst [['2021-43052', 'GuebinChoi', 5, 10, 20, 25],
['2019-12342', 'Heung-min Son', 10, 15, 30, 15],
['2018-32234', 'hynn', 7, 20, 30, 15],
['2022-42323', 'Minji', 8, 20, 20, 35],
['2023-55342', 'Hanni', 7, 20, 30, 35],
['2022-46624', 'Danielle', 3, 15, 30, 40],
['2022-11239', 'Haerin', 10, 20, 30, 40],
['2022-32114', 'Hyein', 10, 20, 20, 35]]
# 문제. 파이썬프로그래밍 수강생의 수는 모두 몇명인가?
(풀이)
len(lst)8
#. 전북대학교 지침에 따라 출석점수가 7보다 작은 학생은 (즉 출석점수 < 7 일 경우) F학점을 부여하게 되어있다. 이 기준에 따르면 F를 받는 학생은 모두 몇명인가?
(풀이)
sum([att<7 for _,_,att,*other in lst])2
# 문제. 파이썬프로그래밍 수업의 경우 출석+레포트 < 21 일 경우 F학점을 부여한다고 한다. 이 기준에 따르면 F를 받는 학생은 모두 몇명인가?
(풀이)
sum([att+rep<21 for _,_,att,rep,*other in lst])2
# 문제. 리스트의 정렬순서를 [학번, 이름, …, 기말고사점수] 가 아니라 [이름, 학번, … , 기말고사점수] 와 같이 되도록 변경하는 코드를 작성하라.
(출력예시)
[['GuebinChoi', '2021-43052', 5, 10, 20, 25],
['Heung-min Son', '2019-12342', 10, 15, 30, 15],
['hynn', '2018-32234', 7, 20, 30, 15],
['Minji', '2022-42323', 8, 20, 20, 35],
['Hanni', '2023-55342', 7, 20, 30, 35],
['Danielle', '2022-46624', 3, 15, 30, 40],
['Haerin', '2022-11239', 10, 20, 30, 40],
['Hyein', '2022-32114', 10, 20, 20, 35]][['GuebinChoi', '2021-43052', 5, 10, 20, 25],
['Heung-min Son', '2019-12342', 10, 15, 30, 15],
['hynn', '2018-32234', 7, 20, 30, 15],
['Minji', '2022-42323', 8, 20, 20, 35],
['Hanni', '2023-55342', 7, 20, 30, 35],
['Danielle', '2022-46624', 3, 15, 30, 40],
['Haerin', '2022-11239', 10, 20, 30, 40],
['Hyein', '2022-32114', 10, 20, 20, 35]]
(풀이)
[[name,sid,*other] for sid,name,*other in lst][['GuebinChoi', '2021-43052', 5, 10, 20, 25],
['Heung-min Son', '2019-12342', 10, 15, 30, 15],
['hynn', '2018-32234', 7, 20, 30, 15],
['Minji', '2022-42323', 8, 20, 20, 35],
['Hanni', '2023-55342', 7, 20, 30, 35],
['Danielle', '2022-46624', 3, 15, 30, 40],
['Haerin', '2022-11239', 10, 20, 30, 40],
['Hyein', '2022-32114', 10, 20, 20, 35]]
4. 잡기술 (하지만 유용해)
A. 인덱싱고급 (스트라이딩)
- 스트라이딩 [start:end:step]
lst = list('abcdefghijk')
lst['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k']
len(lst)11
lst[0:9:2]['a', 'c', 'e', 'g', 'i']
- 생략
lst[0:9]
#lst[0:9:]
#lst[0:9:1]['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
lst[1::3]['b', 'e', 'h', 'k']
lst[:8:3]['a', 'd', 'g']
# 예제1: 짝수/홀수 원소 추출
아래와 같은 문자열이 있다고 하자.
lst = list('abcdefghijk')
lst['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k']
index = 0,2,4, ... 에 해당하는 원소를 출력하라.
lst[::2]['a', 'c', 'e', 'g', 'i', 'k']
index = 1,4,7 ... 에 해당하는 원소를 출력하라.
lst[1::3]['b', 'e', 'h', 'k']
#
# 예제2 – 세로로..
(예제2를 위한 예비학습) 문자열에서 \n을 출력하면 출력시 줄바꿈이 일어난다.
print('1행\n2행\n3행')1행
2행
3행
예비학습 끝
아래와 같은 문자열이 있다고 하자.
txt = '너같이사랑스럽고\n또예쁘고도멋지고\n속훤히보이는너알\n았어그동안고마웠\n지정말정말사랑해'
print(txt)너같이사랑스럽고
또예쁘고도멋지고
속훤히보이는너알
았어그동안고마웠
지정말정말사랑해
위 문자열을 세로로 읽는 코드를 작성하라. (9칸씩 점프하면서 읽으면 된다)
(풀이)
txt[::9]'너또속았지'
#
- step = -1 이면?
lst['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k']
lst[::-1]['k', 'j', 'i', 'h', 'g', 'f', 'e', 'd', 'c', 'b', 'a']
- 스트라이딩으로 step = -1 옵션 주기 vs 리스트의 .reverse() 메소드 이용하기
관찰1: reverse 메소드는 리스트 자체를 변화시킴
lst = list('abcdefgh')
lst['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
lst.reverse()
lst['h', 'g', 'f', 'e', 'd', 'c', 'b', 'a']
관찰2: [::-1]는 리스트는 변화시키지 않음
lst = list('abcdefgh')
lst['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
lst[::-1]['h', 'g', 'f', 'e', 'd', 'c', 'b', 'a']
lst['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
- -step 은 쓰기 까다롭다.
(예제) 처음과 끝을 생략하지 않고 아래와 동일한 효과를 주는 코드를 만들어 보자.
(풀이)
결국 lst[?:?:-1]의 꼴에서 적당히 ?의 값을 채우면 된다. –> 어려워
lst['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
lst[::-1]['h', 'g', 'f', 'e', 'd', 'c', 'b', 'a']
| None | a | b | c | d | e | f | g | h | None |
|---|---|---|---|---|---|---|---|---|---|
| ? | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| -9 | -8 | -7 | -6 | -5 | -4 | -3 | -2 | -1 | ? |
lst[-1:-9:-1] # 지양 <-- 쓰지마..['h', 'g', 'f', 'e', 'd', 'c', 'b', 'a']
B. len함수
- 0차원 자료형은 len함수가 동작하지 않음
a=1
len(a)TypeError: object of type 'int' has no len()
a=True
len(a)TypeError: object of type 'bool' has no len()
a=3.14
len(a)TypeError: object of type 'float' has no len()
note: 이것이 어떠한 수학적인 의미를 가지거나 0차원의 본질적진리를 뜻하는 것은 아님. R에서는 1,3.14,TRUE의 길이가 1로 존재함.
- 1차원 자료형은 len함수가 동작
a='guebin'
len(a)6
a=[1,2,3,4,5,6]
len(a)6
a=1,2,3,4,5,6
len(a)6
a=range(10)
len(a)10
- 길이가 1인 1차원 자료형과 0차원 자료형은 다른것임
a='g'
len(a)1
a=[1]
len(a)1
a=(1,)
len(a)1
a=range(1)
len(a)1
- 길이가 0인 1차원 자료형도 존재함
a=''
len(a)0
a=[]
len(a)0
a=()
len(a)0
a=range(0)
len(a)0
5. dict
A. intro: str, list, tuple 정리
- str, list, tuple은 모두 시퀀스형이라는 공통점이 있다. \(\to\) 원소의 위치번호로 인덱싱이 가능
lst = [1,2,3,4]lst[0] # 위치번호=01
lst[-1] # 위치번호=-14
- str, list, tuple은 차이점도 존재함. 잠깐 정리해보자.
시퀀스형의 카테고리
- 컨테니어형: list, tuple
- 균일형: str
- 가변형: list
- 불변형: tuple, str
표로 정리하면
| 컨테니어형 | 균일형 | |
|---|---|---|
| 가변형 | list | . |
| 불변형 | tuple | str |
- 시퀀스형이 아닌 1차원 자료형도 있을까? 원소의 위치번호로 인덱싱이 불가능한 자료형
- 왜 이런게 필요할까?
- 벡터에서 원소를 뽑는것은 정보의 모임에서 정보를 검색하는 것과 같다.
- 정보를
순서대로 나열한뒤에 그순서를 이용하여 검색하는 방법은 유용하다. - 하지만 경우에 따라서는
키워드를 기억해서 그키워드를 바탕으로 정보에 접근하는 방법이 유용할 수 있다.
카카오톡 대화내용검색
(상황1) 오늘아침에 와이프가 뭔가를 카톡으로 부탁했었음. 그런데 그 뭔가가 기억안남.
(상황2) 방학전에 동료교수과 개강이후 저녁약속을 카톡으로 잡았었음. 그런데 그게 언제인지 기억안남.
- 순서대로 정리된 자료를 검색할때는 시퀀스형이 유리하다. 그런데 키워드로 검색하고 싶을 경우는 딕셔너리 타입이 유리하다.
B. 선언
- 방법1: 가장 일반적
dct = {'guebin':49, 'hanni':80}
dct{'guebin': 49, 'hanni': 80}
- 방법2: dict() 이용
dct = dict(guebin=49, hanni=80)
dct{'guebin': 49, 'hanni': 80}
- 방법3: 중첩된 리스트를 만든 뒤에 형태변환
_lst = [['guebin',49],['hanni',80]]
_lst [['guebin', 49], ['hanni', 80]]
dict(_lst){'guebin': 49, 'hanni': 80}
- 방법4: 중첩된 튜플을 만든 뒤에 형태변환
_tpl = ('guebin',49), ('hanni',80)
_tpl(('guebin', 49), ('hanni', 80))
dict(_tpl){'guebin': 49, 'hanni': 80}
C. 원소추출
- 원소의 위치로 추출할 수 없고, key로 추출해야 한다.
dct = {'guebin':49, 'hanni':80}
dct{'guebin': 49, 'hanni': 80}
guebin의 점수를 추출하고 싶다면?
dct['guebin']49
- 만약에 dict가 아니라 list로 정보를 저장했다면?
(예제) 아래와 같은 리스트에서 guebin의 점수를 추출하고 싶다면?
lst=[['guebin',49],['hanni',80]]
lst[['guebin', 49], ['hanni', 80]]
(풀이1)
lst[0][1] # guebin의 점수를 출력하란 의미49
(풀이2) – 진짜 최악
[lst[i][1] for i in range(len(lst)) if lst[i][0] == 'guebin'][49]
(풀이3) – 덜 최악
[score for name,score in lst if name == 'guebin'][49]
- ’guebin’의 점수를 추출하는 코드 비교
dct['guebin'] # 코드1: 단순하고, 가독성있음49
lst[0][1] # 코드2: 단순하지만, 가독성이 있는건 아님, 확장성이 없음49
[lst[i][1] for i in range(len(lst)) if lst[i][0] =='guebin'] # 코드3: 단순하지도 않고, 가독성도 없음.[49]
[score for name,score in lst if name=='guebin' ] # 코드4: 단순하지 않지만, 가독성은 있음[49]
D. 원소추가, 변경, 삭제
dct={'guebin':49, 'hanni':80}
dct{'guebin': 49, 'hanni': 80}
- 원소에 접근: guebin의 점수 출력
dct['guebin']49
- 추가: hynn학생의 점수를 추가
dct['hynn'] = 99dct{'guebin': 49, 'hanni': 80, 'hynn': 99}
- 변경: hanni의 점수를 변경
dct['hanni'] = 100 dct{'guebin': 49, 'hanni': 100, 'hynn': 99}
- 삭제
(방법1)
dct={'guebin':49, 'hanni':80, 'hynn':99}
del dct['guebin']
dct{'hanni': 80, 'hynn': 99}
(방법2)
dct={'guebin':49, 'hanni':80, 'hynn':99}
dct.pop('guebin')49
dct{'hanni': 80, 'hynn': 99}
- 참고로 리스트였다면 이러한 삭제작업역시 비효율적이었을 것임
lst = [['guebin',49],['hanni',80],['hynn',99]]
lst[['guebin', 49], ['hanni', 80], ['hynn', 99]]
guebin의 점수를 삭제하려면?
[[name,score] for name,score in lst if name != 'guebin'][['hanni', 80], ['hynn', 99]]
E. 연산
- 하나있어요..
dct = {'guebin':49, 'hanni':80}
dct{'guebin': 49, 'hanni': 80}
'guebin' in dctTrue
'hanni' in dctTrue
'hynn' in dctFalse
- in은 사실 다른자료형도 가능했음
(관찰1)
'a' in 'guebin' False
'b' in 'guebin' True
'c' in 'guebin' False
(관찰2)
tpl = 1,2,3
tpl(1, 2, 3)
1 in tplTrue
4 in tplFalse
(관찰3)
lst = [['guebin',49],['hanni',80],['hynn',99]]
lst[['guebin', 49], ['hanni', 80], ['hynn', 99]]
['guebin',49] in lstTrue
- in연산자가 dict형에 사용되면 key를 기준으로 True, False를 판단한다.
F. 딕셔너리 특수기능
(pop)
dct = {'guebin':49, 'hanni':80}
dct.pop('hanni')
dct{'guebin': 49}
(get)
dct = {'guebin':49, 'hanni':80}
dct{'guebin': 49, 'hanni': 80}
dct.get('guebin') 49
아래와 같은 기능
dct['guebin']49
미묘한 차이점이 존재함
dct['hynn'] # hynn이 없어서 키에러 출력, 그런 key는 없다.. KeyError: 'hynn'
dct.get('hynn') # hynn이 없으면 아무것도 출력안함 (keys,values,items)
for k,v in dct.items():
print(k,v)guebin 49
hanni 80
- .keys()는 딕셔너리의 키를 리턴한다.
dct = {'guebin':49, 'hanni':80}
dct{'guebin': 49, 'hanni': 80}
_keys=dct.keys()
_keysdict_keys(['guebin', 'hanni'])
type(_keys) # 리턴된 자료형은 이상한것임dict_keys
list(_keys) # 아무튼 그 이상한 자료형도 리스트화 가능 ['guebin', 'hanni']
- .values()는 딕셔너리의 값들을 리턴한다.
_values = dct.values()
_values dict_values([49, 80])
type(_values)dict_values
list(_values)[49, 80]
- .items()는 딕셔너리의 (키,값)을 리턴한다.
_items = dct.items()
_items dict_items([('guebin', 49), ('hanni', 80)])
type(_items)dict_items
list(_items)[('guebin', 49), ('hanni', 80)]
G. for문과 dict (\(\star\))
dct = {'guebin': 49, 'hanni': 80}
dct{'guebin': 49, 'hanni': 80}
(예시1)
for k in dct.keys():
print(k)guebin
hanni
for k in dct:
print(k)guebin
hanni
- 딕셔너리 그자체도 for문에 넣을 수 있다. 그때는 딕셔너리의 key가 반복된다.
- 결과를 보면 dct 대신에 dct.keys()와 list(dct)를 넣었을때와 결과가 같다.
Note: list(dct) 하면 key만 리턴된다.
(예시2)
for v in dct.values():
print(v)49
80
(예시3)
for i in dct.items():
print(i)('guebin', 49)
('hanni', 80)
(예시4)
for k,v in dct.items():
print(k,v)guebin 49
hanni 80
(예시5) – {}의 중간고사 점수는 {}점 입니다.
for name,score in dct.items():
print(f'{name}의 중간고사 점수는 {score}점 입니다.')guebin의 중간고사 점수는 49점 입니다.
hanni의 중간고사 점수는 80점 입니다.
H. dict에서 key혹은 value만 뽑아내기
- 예제: 아래의 dict에서 key만 뽑아내고 싶다.
dct = {'guebin':49, 'hanni':80} (풀이1)
list(dct)['guebin', 'hanni']
(풀이2)
list(dct.keys())['guebin', 'hanni']
(풀이3)
[k for k in dct]['guebin', 'hanni']
(풀이4)
[k for k,v in dct.items()]['guebin', 'hanni']
- 예제: 아래의 dict에서 value만 뽑아내고 싶다.
dct = {'guebin':49, 'hanni':80} (풀이1)
list(dct.values())[49, 80]
(풀이2)
[dct[k] for k in dct][49, 80]
(풀이3)
[v for v in dct.values()][49, 80]
(풀이4)
[v for k,v in dct.items()][49, 80]
6. 딕셔너리를 이용한 치환 (\(\star\))
A. 바꿔치기
# 예제1 – 아래와 같은 리스트를 고려하자.
lst = ['딸기','사과','바나나','딸기','사과','오토바이','자동차','버스','기차','오토바이','자동차']다음의 맵핑규칙에 따라서 위의 리스트의 원소를 바꾸어라.
| 변환전 | 변환후 |
|---|---|
| 딸기 | 과일 |
| 사과 | 과일 |
| 바나나 | 과일 |
| 오토바이 | 탈것 |
| 자동차 | 탈것 |
| 버스 | 탈것 |
| 기차 | 탈것 |
(풀이1) – elif를 한번 써본정도의 의미. 추천하는 풀이 X
lst2 = []
for l in lst:
if l=='딸기':
lst2.append('과일')
elif l=='사과':
lst2.append('과일')
elif l=='바나나':
lst2.append('과일')
elif l=='오토바이':
lst2.append('탈것')
elif l=='자동차':
lst2.append('탈것')
elif l=='버스':
lst2.append('탈것')
else:
lst2.append('탈것') lst,lst2(['딸기', '사과', '바나나', '딸기', '사과', '오토바이', '자동차', '버스', '기차', '오토바이', '자동차'],
['과일', '과일', '과일', '과일', '과일', '탈것', '탈것', '탈것', '탈것', '탈것', '탈것'])
(풀이2) – 코드는 쉽고 편함. dct를 만들기 힘듦.
dct = {'딸기':'과일','사과':'과일','바나나':'과일','오토바이':'탈것','자동차':'탈것','버스':'탈것','기차':'탈것'}
dct{'딸기': '과일',
'사과': '과일',
'바나나': '과일',
'오토바이': '탈것',
'자동차': '탈것',
'버스': '탈것',
'기차': '탈것'}
[dct[l] for l in lst]['과일', '과일', '과일', '과일', '과일', '탈것', '탈것', '탈것', '탈것', '탈것', '탈것']
(풀이3) – 코드가 매우 어려움. dct를 만들기 쉬움.
dct = {'과일':['딸기','사과','바나나'], '탈것':['오토바이','자동차','버스','기차']}
dct{'과일': ['딸기', '사과', '바나나'], '탈것': ['오토바이', '자동차', '버스', '기차']}
lst['딸기', '사과', '바나나', '딸기', '사과', '오토바이', '자동차', '버스', '기차', '오토바이', '자동차']
[k for l in lst for k in dct if l in dct[k]]['과일', '과일', '과일', '과일', '과일', '탈것', '탈것', '탈것', '탈것', '탈것', '탈것']
#
# 예제2 – 아래와 같은 리스트가 있다고 하자.
lst = list('abcd'*2+'bbb')
lst['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd', 'b', 'b', 'b']
아래의 규칙에 의하여 lst의 각 원소의 값을 바꾸고 싶다고 하자. 이를 구현하는 코드를 작성하라.
| 변환전 | 변환후 |
|---|---|
| ‘a’ | [1,0,0,0] |
| ‘b’ | [0,1,0,0] |
| ‘c’ | [0,0,1,0] |
| ‘d’ | [0,0,0,1] |
(풀이)
dct = {'a':[1,0,0,0], 'b':[0,1,0,0], 'c':[0,0,1,0], 'd':[0,0,0,1]}
dct{'a': [1, 0, 0, 0], 'b': [0, 1, 0, 0], 'c': [0, 0, 1, 0], 'd': [0, 0, 0, 1]}
[dct[l] for l in lst][[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1],
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1],
[0, 1, 0, 0],
[0, 1, 0, 0],
[0, 1, 0, 0]]
# 예제3 – 예제2을 역변환하라. 즉 아래의 리스트를
lst2= [[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1],
[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1],
[0, 1, 0, 0],
[0, 1, 0, 0],
[0, 1, 0, 0]]아래와 같이 바꾸라.
['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd', 'b', 'b', 'b']['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd', 'b', 'b', 'b']
(풀이) – 실패
dct = {[1,0,0,0]:'a', [0,1,0,0]:'b', [0,0,1,0]:'c', [0,0,0,1]:'d'}
dctTypeError: unhashable type: 'list'
dct의 key에 대응하는것은 불변형만 가능
(풀이1)
dct = {(1,0,0,0):'a', (0,1,0,0):'b', (0,0,1,0):'c', (0,0,0,1):'d'}
dct{(1, 0, 0, 0): 'a', (0, 1, 0, 0): 'b', (0, 0, 1, 0): 'c', (0, 0, 0, 1): 'd'}
[dct[tuple(l)] for l in lst2]['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd', 'b', 'b', 'b']
(풀이2)
dct = {'a':[1,0,0,0], 'b':[0,1,0,0], 'c':[0,0,1,0], 'd':[0,0,0,1]} # 예제2의 dct[k for l in lst2 for k in dct if dct[k]==l]['a', 'b', 'c', 'd', 'a', 'b', 'c', 'd', 'b', 'b', 'b']
B. 연습문제
# 문제. 아래와 같은 맵핑을 고려하자.
| 문자 | 숫자 |
|---|---|
| a | 0 |
| b | 1 |
이를 딕셔너리로 표현하면 아래와 같다.
dct = {'a':0, 'b':1} 위 규칙에 따라서 아래의 리스트의 원소를 문자로 각각 변환하라.
lst = [1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1]# 출력은 아래와 같아야 한다.
['b', 'a', 'b', 'a', 'b', 'a', 'b', 'b', 'b', 'b', 'a', 'a', 'b', 'a', 'b'](풀이)
[k for l in lst for k in dct if l == dct[k]]['b', 'a', 'b', 'a', 'b', 'a', 'b', 'b', 'b', 'b', 'a', 'a', 'b', 'a', 'b']
# 문제. 아래와 같은 맵핑을 고려하자.
| 월 | 의미 |
|---|---|
| 1,2 | 겨울방학 |
| 3,4,5,6 | 1학기 |
| 7,8 | 여름방학 |
| 9,10,11,12 | 2학기 |
이러한 규칙에 맞게 아래의 리스트를 적절한 문자열로 변환하라.
month = [1,2,2,3,4,5,6,7,8,9,9,10,11,12] ## 출력은 아래와 같아야 한다.
['겨울방학', '겨울방학', '겨울방학', '1학기', '1학기', '1학기', '1학기', '여름방학', '여름방학', '2학기', '2학기', '2학기', '2학기', '2학기'](풀이1) – 좀 더 추천함
dct = {'겨울방학':range(1,3), '1학기':range(3,7), '여름방학':range(7,9), '2학기':range(9,13)}[k for m in month for k in dct if m in dct[k]]['겨울방학',
'겨울방학',
'겨울방학',
'1학기',
'1학기',
'1학기',
'1학기',
'여름방학',
'여름방학',
'2학기',
'2학기',
'2학기',
'2학기',
'2학기']
(풀이2) – 추천안함
dct = {1:'겨울방학',2:'겨울방학',3:'1학기',4:'1학기',5:'1학기',6:'1학기',7:'여름방학',8:'여름방학',9:'2학기',10:'2학기',11:'2학기',12:'2학기'}[dct[m] for m in month]['겨울방학',
'겨울방학',
'겨울방학',
'1학기',
'1학기',
'1학기',
'1학기',
'여름방학',
'여름방학',
'2학기',
'2학기',
'2학기',
'2학기',
'2학기']
## – 합성변환
아래와 같은 맵핑을 고려하자.
(규칙1)
| 문자 | 숫자 |
|---|---|
| 바나나 | 0 |
| 사과 | 1 |
| 오토바이 | 2 |
| 자동차 | 3 |
| 자전거 | 4 |
(규칙2)
| 아이템 | 카테고리 |
|---|---|
| 바나나 | 과일 |
| 사과 | 과일 |
| 오토바이 | 탈것 |
| 자동차 | 탈것 |
| 자전거 | 탈것 |
각각의 규칙을 나타내는 딕셔너리는 아래와 같이 선언되어있다고 하자.
dct1 = {'바나나':0, '사과':1, '오토바이':2, '자동차':3, '자전거':4}
dct2 = {'과일':['바나나','사과'], '탈것':['오토바이','자동차','자전거']} # 문제. 규칙1를 이용하여 아래와 같은 리스트를 변환하는 함수를 구현하고 그 함수를 f라 선언하라.
# 입력
[0,1,0,1,4]
# 출력
['바나나', '사과', '바나나', '사과', '자전거'](사용예시)
f([0,1,0,1,4])['바나나', '사과', '바나나', '사과', '자전거']
(풀이)
f = lambda lst: [k for l in lst for k in dct1 if l == dct1[k]]f([0,1,0,1,4])['바나나', '사과', '바나나', '사과', '자전거']
# 문제. 규칙2를 이용하여 아래와 같이 리스트를 변환하는 함수를 구현하고 그 함수를 g라고 선언하라.
# 입력
['바나나','바나나','바나나','자동차']
# 출력
['과일','과일','과일','탈것'](사용예시)
g(['바나나','바나나','바나나','자동차'])['과일', '과일', '과일', '탈것']
(풀이)
g = lambda lst: [k for l in lst for k in dct2 if l in dct2[k]]g(['바나나','바나나','바나나','자동차'])['과일', '과일', '과일', '탈것']
# 문제. 규칙1-2를 이용하여 아래와 같은 숫자로 이루어진 입력을 ‘과일’, ‘탈것’ 중 하나로 바꾸는 코드를 구현하라.
# 입력
[0,1,0,1,3,4,2,2,3,4,1,0]
# 출력
['과일', '과일', '과일', '과일', '탈것', '탈것', '탈것', '탈것', '탈것', '탈것', '과일', '과일']hint \(g(f(x))\) 를 이용하라.
(풀이)
g(f([0,1,0,1,3,4,2,2,3,4,1,0]))['과일', '과일', '과일', '과일', '탈것', '탈것', '탈것', '탈것', '탈것', '탈것', '과일', '과일']
7. 파이썬 자료형 연습문제
Oxford-III: // reference
아래는 이미지 파일명들이 저장된 string을 불러오는 코드이다.
import requests
url = 'https://raw.githubusercontent.com/guebin/PP2023/main/posts/01_PythonBasic/Oxford-IIIT.txt'
txt = requests.get(url).content.decode()txt의 출력 일부를 나타내면 아래와 같다.
'Abyssinian_1.jpg\nAbyssinian_10.jpg\nAbyssinian_100.jpg\nAbyssinian_100.mat\nAbyssinian_101.jpg\nAbyssinian_101.mat\nAbyssinian_102.jpg\nAbyssinian_102.mat\nAbyssinian_103.jpg\nAbyssinian_104.jpg\nAbyssinian_105.jpg\nAbyssinian_106.jpg\nAbyssinian_107.jpg\nAbyssinian_108.jpg\nAbyssinian_109.jpg\nAbyssinian_11.jpg\nAbyssinian_110.jpg\nAbyssinian_111.jpg\nAbyssinian_112.jpg\nAbyssinian_113.jpg\nAbyssinian_114.jpg\nAbyssinian_115.jpg\nAbyssinian_116.jpg\nAbyssinian_117.jpg\nAbyssinian_118.jpg\nAbyssinian_119.jpg\nAbyssinian_12.jpg\nAbyssinian_120.jpg\nAbyssinian_121.jpg\nAbyssinian_122.jpg\nAbyssinian_123.jpg\nAbyssinian_124.jpg\nAbyssinian_125.jpg\nAbyssinian_126.jpg\nAbyssinian_127.jpg\nAbyssinian_128.jpg\nAbyssinian_129.jpg\nAbyssinian_13.jpg\nAbyssinian_130.jpg\nAbyssinian_131.jpg\nAbyssinian_132.jpg\n ....... # 문제. 각 파일명은 \n으로 구분되어있다. 위의 스트링을 분해하여 아래와 같은 리스트를 생성하고 fname_list에 저장하라.
# fname_list 의 출력결과는 아래와 같아야 한다.
['Abyssinian_1.jpg','Abyssinian_10.jpg', ... ,'yorkshire_terrier_98.jpg', 'yorkshire_terrier_99.jpg'](풀이)
fname_list = txt.split('\n')
fname_list[:5] # 7393개의 이미지파일명이 저장되어있음. ['Abyssinian_1.jpg',
'Abyssinian_10.jpg',
'Abyssinian_100.jpg',
'Abyssinian_100.mat',
'Abyssinian_101.jpg']
# 문제. 각 이미지파일명은 아래와 같은 규칙으로 저장되어 있다.
- 파일명의 첫글자가 대문자이면 고양이를 의미하고 첫글자가 소문자이면 강아지를 의미한다.
이미지 파일명이 입력으로 오면 강아지인지 고양이인지 판단하여 ‘cat’ or ’dog’를 리턴하는 함수 f를 구현하라.
(함수사용예시)
f('yorkshire_terrier_99.jpg')'dog'
f('Abyssinian_1.jpg')'cat'
(풀이)
f = lambda s: 'cat' if s[0].isupper() else 'dog'
f('Abyssinian_1.jpg')'cat'
# 문제. 위의 결과로 나온 fname_list를 입력으로 하고 리스트의 각 원소가 고양이를 의미하는 그림인지 강아지를 의미하는 그림인지 나타내는 리스트를 만들어라.
## 입력예시
['Abyssinian_1.jpg','Abyssinian_10.jpg',...,'yorkshire_terrier_98.jpg', 'yorkshire_terrier_99.jpg']
## 출력예시
['cat', 'cat', ... , 'dog', 'dog'](풀이1)
#list(map(f,fname_list))(풀이2)
#[f(fname) for fname in fname_list]# 문제. 강아지 그림과 고양이 그림이 각각 몇 장씩 포함되어 있는지 파악하는 코드를 구현하라.
(풀이)
[f(fname) for fname in fname_list].count('cat')2403
[f(fname) for fname in fname_list].count('dog')4990
# 문제. 고양이 혹은 강아지의 각 종이 몇 장씩 포함되어있는지 구하여 딕셔너리로 정리하라.
(풀이)
lst = ['_'.join(l.split('_')[:-1]) for l in fname_list]
{s:lst.count(s) for s in set(lst)}{'yorkshire_terrier': 200,
'Siamese': 200,
'chihuahua': 200,
'Persian': 200,
'miniature_pinscher': 200,
'samoyed': 200,
'boxer': 200,
'american_pit_bull_terrier': 200,
'german_shorthaired': 200,
'great_pyrenees': 200,
'Sphynx': 200,
'shiba_inu': 200,
'american_bulldog': 200,
'havanese': 200,
'Bombay': 200,
'japanese_chin': 200,
'Ragdoll': 200,
'english_cocker_spaniel': 200,
'english_setter': 200,
'Egyptian_Mau': 200,
'staffordshire_bull_terrier': 191,
'Russian_Blue': 200,
'beagle': 200,
'pomeranian': 200,
'British_Shorthair': 200,
'pug': 200,
'Bengal': 200,
'newfoundland': 200,
'wheaten_terrier': 200,
'Abyssinian': 203,
'Maine_Coon': 200,
'basset_hound': 200,
'saint_bernard': 200,
'scottish_terrier': 199,
'keeshond': 200,
'leonberger': 200,
'Birman': 200}