Lesson 03: 파이썬 자료형 심화개념
튜플고급
튜플을 왜 쓰지? (1)
그냥 리스트를 쓰면 되는거 아닌가 하는 생각이 듭니다. 그냥 튜플은 값이 바뀌지 않는 리스트 느낌. 이게 왜 쓸모있지?
- 책의설명: 코딩을 하다보면 값을 바꾸지 말아야 할 것을 실수로 값을 바꾸는 경우가 있음. 이런 실수를 방지할 수 있다.
- shallow copy/deep copy 에 대한 개념을 모르면 생기는 여러가지 side effect이 있음. 이러한 side effect을 막을 수 있는 무기임.
슬기로운 튜플 사용 (\(\star\star\star\star\star\))
상황1: 다중출력(?)
- 예제: 여러변수를 동시에 출력하고 싶을 경우 (다중출력?)
변수를 아래와 같이 선언하였다고 하자.
선언된 값을 확인하려면?
튜플을 이용하면?
상황2: 다중할당
- 예제: 다중할당1 (여러개의 변수를 동시에 선언하고 싶을 경우)
- 예제: 다중할당2, 위도와 경도
- 잠깐만: 다중할당은 꼭 튜플에서만 가능한가?
그건 아니다…
튜플과 같이 사용하면 가독성이 극대화 (그래서 다중할당은 거의 튜플과 세트로 사용함)
상황3: 변수값을 교환
- 예제: 임시변수 사용없이 두 변수의 값을 교환
상황4: for문과 함께
- 예제: for문과 튜플
[['guebin', 202112345, 'M'],
['iu', 202254321, 'F'],
['hodong', 202011223, 'M']]
- 예제: for문과 튜플, dummy variable _
- 예제: for문과 튜플, * 연산자
(motive)
- 귀찮냐..
(신기술)
상황4: 언패킹연산자와 함께
- 예제: 튜플과 언패킹연산자 *
(1, 2, [3, 4, 5, 6, 7], 8, 9, 10)
Appendix: 언패킹연산자
(관찰)
그러고 보니까..
head1,head2, body, tail1,tail2,tail3 = (1, 2, [3,4,5,6,7], 8, 9, 10)
head1,head2, *body, tail1,tail2,tail3 = (1, 2, 3,4,5,6,7, 8, 9, 10)이렇다는 거잖아?
*를 붙이면 1차원 자료구조가 풀린다..?
SyntaxError: can't use starred expression here (<ipython-input-6-a543979d8d3c>, line 4)
튜플을 왜 쓰지? (2)
- 책의 설명 (이 설명이 꼭 파이썬에 한정되는 것은 아님. 모든 언어에 존재하는 불변형 객체에 적용가능한 설명)
- 실수방지
- 빠르다, 다중작업에 유리하다, 여러사람과 작업하기에 유리하다, 깊은복사/얕은복사시 원하지않는 오류(side effect이라고 함)를 방지할 수 있다, 메모리관리에도 유리함…
- 느낌: 불변형은 기능제한이 있는데 가볍고 빠른, 가변형은 기능은 풍부하지만 약간 느리고 무거운 느낌임 (불변형:라면사리, 가변형:라면)
- 제 생각
- 튜플의 장점은 소괄호의 생략에 있음 (이것은 파이썬과 줄리아만 가능)
- 이것이 언패킹구문과 결합하여 엄청난 가독성을 제공
(예시) 튜플의 막강함
- 의문: 왜 튜플만 괄호를 생략할 수 있지?
- 내 망상
- 튜플을 먼저 만들고, 괄호를 생략하는 문법을 추가한것은 아닐것임
- 원래 괄호없이 컴마만 대충찍어서 선언가능한 아주 간단한 타입의 벡터형을 만들고 싶었을 것임.
- 왜? 괄호없는 벡터를 만들고 + 언패킹을 사용하면 여러가지 구문들이 엄청나게 간단해짐.
- 컴마컴마로 선언하는 벡터는 한 두번 쓰고 버리는 경우가 많으며 대부분 이름도 필요없음 \(\to\) 원소에 접근해서 sorting하여 순서를 바꾸고 싶다던가 원소를 추가할 이유가 없음 \(\to\) 비싼 가변형으로 만들 이유가 없다는 것..
- 우리가 필요한 것: 데이터가 벡터의 형태로 모여있기만 하면 된다!
- 다른 사람들 의견 (컴공과 인터뷰)
- 튜플 + 언패킹에 충격 \(\to\) 파이썬 편하더라..
인덱싱고급 (스트라이딩)
- 스트라이딩 [start:stop:step]
- 생략
- 예제: 짝수/홀수 원소 추출
- step = -1 이면?
- reverse와 같은 기능
(reverse)와 비교
관찰1: reverse 메소드는 리스트 자체를 변화시킴
관찰2: [::-1]는 리스트는 변화시키지 않음
- 사실 -step은 쓰는 것이 조금 까다롭다.
(예제) 처음과 끝을 생략하지 않고 아래와 동일한 효과를 주는 코드를 만들어 보자.
(풀이)
결국 lst[?:?:-1]의 꼴에서 적당히 ?의 값을 채우면 된다.
잠깐 인덱스를 생각해보자.
| a | b | c | d | e | f | g | h |
|---|---|---|---|---|---|---|---|
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| -8 | -7 | -6 | -5 | -4 | -3 | -2 | -1 |
(예제)
결론: -step을 자주 쓰진 말자?
컴프리헨션 고급 (if문이 포함된 컴프리헨션)
- 예제: 제곱수중에서 12로 나누어 떨어지는 수만 원소로 가지는 리스트를 만들고 싶다.
- 제곱수: 1,4,9,16,25,36, …
- 12로 나누어 떨어지는 수: 36, …
(예비학습)
(풀이1)
(풀이2)
함수고급 (조건부리턴)
- 홀수/짝수를 판별하는 함수 만들기 1
['odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even', 'odd', 'even']
- 홀수/짝수를 판별하는 함수 만들기 2
len함수
- 0차원 자료형은 len함수가 동작하지 않음
note: 이것이 어떠한 수학적인 의미를 가지거나 0차원의 본질적진리를 뜻하는 것은 아님. R에서는 1,3.14,TRUE의 길이가 1로 존재함.
- 1차원 자료형은 len함수가 동작
- 길이가 1인 1차원 자료형과 0차원 자료형은 다른것임
- 길이가 0인 1차원 자료형도 존재함
str, list, tuple 비교
- str, list, tuple은 모두 시퀀스형이라는 공통점이 있다. \(\to\) 원소의 위치번호로 인덱싱이 가능
- str, list, tuple은 차이점도 존재함. 잠깐 정리해보자.
시퀀스형의 카테고리
- 컨테니어형: list, tuple
- 균일형: str
- 가변형: list
- 불변형: tuple, str
표로 정리하면
| 컨테니어형 | 균일형 | |
|---|---|---|
| 가변형 | list | . |
| 불변형 | tuple | str |
- 시퀀스형이 아닌 1차원 자료형도 있을까? (이원소의 위치번호로 인덱싱이 불가능한 자료형
Quiz
ssh코드: 1-2
아래의 문자열을 고려하자.
test_arr = 'ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSUGPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XAt3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/EnmZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbxNrRFi9wrf+M7Q== schacon@mylaptop.local'1. 이 문자열에서 index = 0,2,4,6,8,... 에 해당하는 원소를 출력하는 코드를 작성하라.
'shraAABNa1cEAAIAAEkOpDrH1SrTpLG9jmBDUP+azHTWhIy5w8HJ9bUriz7lLV49F5VbpSgcaPvkd/TBWFRHoFRtqi1KXHZMiqVRsAwsMvlK7A3aJAnMQx+VW6/Im1uFjJpr8XpDjNyv/bretEm+WOPTI9PVLar2E6/lbg331KtIj2od1rTMVsxrF9r+7= cao@yatplcl'
2. 위 문자열을 뒤집은 문자열을 구하는 코드를 구현하라.
'lacol.potpalym@nocahcs ==Q7M+frw9iFRrNxbsSVqMlTarQ10d1os2njkImtaKn1+3r3wg+b8li/Z68Ec2DryauLMVmPZ98IPTnPZO4WA+ZmnE/trewr0bP/wv6ybNYjvDNpyX88XrrpKJQjlFUuz1bmFIe/86wW0V3+5x9Q1McnsAoJoaF3tAX7/KVlSvFMdsdwQANsjR6V8qLicMsZAHpXhKn1XixqBtiRXF3oAH+RCFXWlByTM/JdOk7vbP3adc0gwSppPbkVQ5XFl9h4fVELElx7MzQivrFUhbj9WJ4HJ81we5Zy4Idh7WYTDHlzfan+lPGUSDWB/mojT9KGTLNpITmrbS71YHfrHDkpUOlkAEQAAAwIBAAAAE2cy1CazN3BAAAA asr-hss'
파이썬 프로그래밍 시험성적: 3-4
아래와 같은 dictionary가 있다고 가정하자.
dct={'202212377': {'att': 65, 'rep': 45, 'mid': 0, 'fin': 10},
'202212473': {'att': 95, 'rep': 30, 'mid': 60, 'fin': 10},
'202212310': {'att': 65, 'rep': 85, 'mid': 15, 'fin': 20},
'202212460': {'att': 55, 'rep': 35, 'mid': 35, 'fin': 5},
'202212320': {'att': 80, 'rep': 60, 'mid': 55, 'fin': 70},
'202212329': {'att': 75, 'rep': 40, 'mid': 75, 'fin': 85},
'202212408': {'att': 65, 'rep': 70, 'mid': 60, 'fin': 75},
'202212319': {'att': 60, 'rep': 25, 'mid': 20, 'fin': 35},
'202212348': {'att': 95, 'rep': 55, 'mid': 65, 'fin': 90},
'202212306': {'att': 90, 'rep': 25, 'mid': 95, 'fin': 50},
'202212308': {'att': 55, 'rep': 45, 'mid': 75, 'fin': 30},
'202212366': {'att': 95, 'rep': 60, 'mid': 25, 'fin': 55},
'202212367': {'att': 95, 'rep': 35, 'mid': 0, 'fin': 25},
'202212461': {'att': 50, 'rep': 55, 'mid': 90, 'fin': 45}}여기에서 ‘202212377’ 등은 학번을, att는 출석점수, rep는 레포트점수, mid는 중간고사 점수, fin은 기말고사 점수를 의미한다.
3. 학생들의 학번을 아래와 같은 방식으로 출력하는 코드를 작성하라.
['202212377',
'202212473',
'202212310',
'202212460',
'202212320',
'202212329',
'202212408',
'202212319',
'202212348',
'202212306',
'202212308',
'202212366',
'202212367',
'202212461']
4. 출석점수가 70점 이상인(>=70) 학생들의 학번을 출력하는 코드를 작성하라.
['2022-12473',
'2022-12320',
'2022-12329',
'2022-12348',
'2022-12306',
'2022-12366',
'2022-12367']
Oxford-III: 5–10 // reference
아래는 이미지 파일명들이 저장된 string을 불러오는 코드이다.
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 ....... 5. 각 파일명은 \n으로 구분되어있다. 위의 스트링을 분해하여 아래와 같은 리스트를 생성하고 fname_list에 저장하라.
# fname_list 의 출력결과는 아래와 같아야 한다.
['Abyssinian_1.jpg','Abyssinian_10.jpg', ... ,'yorkshire_terrier_98.jpg', 'yorkshire_terrier_99.jpg']6. 각 이미지파일명은 아래와 같은 규칙으로 저장되어 있다.
- 파일명의 첫글자가 대문자이면 고양이를 의미하고 첫글자가 소문자이면 강아지를 의미한다.
_이전의 영문명은 고양이 혹은 강아지의 종(breed)을 의미한다.
이미지 파일명이 입력으로 오면 강아지인지 고양이인지 판단하여 ‘cat’ or ’dog’를 리턴하는 함수 f를 구현하라.
(함수사용예시)
7. 5의 결과로 나온 fname_list를 입력으로 하고 리스트의 각 원소가 고양이를 의미하는 그림인지 강아지를 의미하는 그림인지 나타내는 리스트를 만들어라.
## 입력예시
['Abyssinian_1.jpg','Abyssinian_10.jpg',...,'yorkshire_terrier_98.jpg', 'yorkshire_terrier_99.jpg']
## 출력예시
['cat', 'cat', ... , 'dog', 'dog']8. 강아지 그림과 고양이 그림이 각각 몇 장씩 포함되어 있는지 파악하는 코드를 구현하라.
hint 고양이 2403, 강아지 4990
9. 포메라니안 종의 그림이 몇장있는지 파악하는 코드를 구현하라.
hint: 포메라니안 그림은 파일명에 ‘pomeranian’ 을 포함한다.