0614 - 0620
0614
테스트 2차 준비 1일차
오늘부터 2차테스트 준비에 돌입했다.
이번 주에 학습할 내용은 파이썬이다.
전부터 코딩테스트를 준비할 때 파이썬이 좋다는 말은 많이 들었지만, 평소에 많이 했던 자바로 할지 파이썬을 새로 익히는게 좋을지 고민을 했던 기억이 있다.
이번에 파이썬을 내 것으로 만들어서 코딩테스트에 큰 도움이 되었으면 한다.
비록 하루 공부해보았지만, 파이썬은 정말 자유롭고 flexible한 언어인 것 같다.
정말 큰 정수도 쉽게 사용할 수 있고, 일반적인 프로그래밍 언어에서 자주보던 세미콜론도 찾아볼 수 없었다.
매력적인 언어를 발견한 것 같다.
기초
파이썬 언어 장점
- 문법이 간결
- 다양한 운영체제 지원
- GUI Application 개발(PyQT)
- 방대한 라이브러리 지원
- 범용 언어(네트워크 웹, 데이터분석, 기계학습 등)
Print 함수의 이해
- 가장 기본적인 Output(출력) 함수
- 기본 출력
- Separator, End 옵션 사용
- Format 형식 출력
- Escape Code 사용법
기본 출력
print('Hello Python!')
print("Hello Python!")
print("""Hello Python!""")
print('''Hello Python!''')
- 모두 같은 문자열을 반환한다.
Separator 옵션
sep=
뒤에 오는 문자열을 print 함수 내에 있는 ,으로 연결되어 있는 문자 사이에 삽입하여 반환한다.
print('T', 'E', 'S', 'T', sep='')
print('2021', '6', '14', sep='-')
print('niceman', 'google.com', sep='@')
# 결과
TEST
2021-6-14
niceman@google.com
End 옵션
end=
뒤에 오는 문자열을 print 함수 내에 있는 문자열 마지막에 삽입하여 반환한다. (개행 x)
print('Welcome To', end=' ')
print('the black parade', end=' ')
print('piano notes')
# 결과
Welcome To the black parade piano notes
Format 형식 출력
print('{} and {}'.format('You', 'Me'))
print('{0} and {1} and {0}'.format('You', 'Me'))
print('{a} and {b}'.format(a='You', b='Me'))
# 결과
You and Me
You and Me and You
You and Me
- 빈 중괄호를 사용하여 문자열이 끝난 뒤 .format()을 사용해 빈 문자열에 해당하는 단어를 정해줄 수 있다.
- 0, 1, 2 등의 값을 중괄호 안에 넣어 format() 파라미터 순서에 해당하는 문자를 삽입할 수 있다.
- a, b 처럼 단어를 중괄호 안에 넣어 format() 안에서 해당 단어를 정의하여 그에 해당하는 문자를 삽입할 수 있다.
# %s : 문자, %d : 정수, %f : 실수
print("%s's favorite number is %d" % ('Eunki', 7))
print('Test1: %5d, price: %4.2f' % (776, 6534.123))
print('Test1: {0:5d}, price: {1:4.2f}'.format(776, 6534.123))
print('Test1: {a:5d}, price: {b:4.2f}'.format(a=776, b=6534.123))
- 위와 같이 출력할 타입의 형식을 정의하여 사용하는 방식도 있는데 사용법은 위와 같이 크게 두가지로 나뉜다.
- %를 사용하여 출력하는 경우는 .format 대신 %로 사이를 연결하고 중괄호를 사용하여 출력하는 경우는 중괄호 안에
숫자or문자:출력타입형식
으로 사용한다. - 5d는 정수를 5자리수로 나타낸다는 뜻이고, 4.2f는 4자리의 정수와 2자리의 소수점 아래 수를 의미한다.
Escape 코드
\n
: 개행\t
: 탭\\
: 문자\'
: 문자\"
: 문자- 위에 5가지가 주로 사용된다.
- 문자 ‘나 “는 프린트 함수 안에서 사용되는 것과 의미가 혼용될 수 있기 때문에, 이스케이프 코드를 사용하여 나타내면 출력할 수 있다.
기초 몸 풀기 코딩
- 파이썬의 기본 입출력 인코딩은 UTF-8이다.
- 변수나 함수 선언은 한글로도 가능하지만 사용하면 안 된다.
파이썬 가상 환경
가상환경 설정 및 패키지 설치
가상환경 필요성
- 환경변수를 잘 관리하지 못한다면, 한 운영체제에 같은 프로그램을 버전만 다르게 이것저것 설치하면 충돌이 발생해서 되던 것이 안될 수도 있다.
-> 별개의 가상환경을 통해서 여러 프로젝트를 할때 다른 모듈을 사용하더라도 매우 깔끔하게 환경을 구성할 수 있다.
설정
python3 -m venv 폴더이름
- 맥북의 경우 python 명령어 대신 python3를 사용
- 폴더 이름의 폴더가 있으면 해당 폴더에 가상환경을 설정하고 없을 경우 생성한 뒤 설정한다.
- 해당 폴더 내부에 bin (맥북의 경우), include, lib 폴더가 생성된다.
활성화, 비활성화 명령어
- 맥북의 경우 bin 폴더, 윈도우의 경우 scripts 폴더로 이동한다.
- 맥북의 경우
source ./activate
, 윈도우의 경우activate.bat
명령어를 입력하면 가상환경이 활성화한다. - 맥북의 경우
deactivate
, 윈도우의 경우deactivate.bat
명령어를 입력하면 가상환경을 빠져나간다.
패키지 관련 명령어
- pip list : 해당 가상환경에 설치되어 있는 목록을 출력한다.
- pip install simplejson : simplejson 패키지를 가상환경에 설치한다.
- pip uninstall simplejson : simplejson 패키지를 가상환경에서 제거한다.
- pip install –upgrade simplejson : simplejson 패키지를 최신 버전으로 업그레이드한다.
- pip search simplejson : simplejson 패키지를 검색한다. 현재는 비활성화 되어 있는 상태
- pip show simplejson : simplejson 패키지에 대한 정보들을 출력한다.
파이썬 데이터 타입
- Boolean
- Numbers
- String
- Bytes
- Lists
- Tuples
- Sets
- Dictionaries
파이썬 숫자형 및 연산자
+
: 더하기-
: 빼기*
: 곱하기/
: 나누기//
: 나누기(몫)%
: 나누기(나머지)**
: 지수(제곱)- 단항 연산자
특징
- 문자열 안에 삽입된 기호는 그대로 출력된다.
- 정수와 실수를 더하면 결과 타입은 실수이다.
//
연산의 결과는 피연산자가 실수이면 실수가 된다.-
- 는 5.0이고, .4는 0.4를 나타낸다.
형 변환
- type(x) 연산자를 사용해서 x의 타입을 알 수 있다.
- 형 변환 연산자는
변환하고싶은타입(변환하고싶은값)
형식으로 사용하면 해당 값이 원하는 타입으로 변한다. - 변환할 수 있는 타입의 종류로는 float, int, complex(복소수)가 있는데 재밌는 사실은 Boolean 값인 True나 False를 int, false, complex로 변환할 수 있다.
수치 연산 함수
print(abs(-7))
x, y = divmod(100, 8)
print(x, y)
print(pow(5, 3))
# 결과
7
12 4
125
- abs() 함수는 파라미터 값의 절대값을 반환한다.
- divmod(x, y) 함수는 x를 y로 나눠서 몫과 나머지를 반환한다.
- pow(x, y)는 x를 y제곱한 결과를 반환한다. (
x ** y
의 결과값과 같다.)
외부 모듈 math
import math
를 입력하여 math 함수를 사용할 수 있다.- math.ceil() 함수는 파라미터 값을 올림한 정수값을 반환한다.
- math.floor() 함수는 파라미터 값을 내림한 정수값을 반환한다.
- math 함수 문서
문자형 관련 연산자
문자열 생성, 길이
# 문자열 생성
str1 = "I am Boy."
str2 = 'NiceMan'
str3 = """How are you?"""
str4 = '''Thank you!'''
# 문자열 길이
print(len(str1))
- 문자열 길이는 len() 함수를 사용해 숫자로 반환한다.
빈 문자열
str_t1 = ''
str_t2 = str()
- 같은 공백의 문자열 반환
Raw String
- 문자열을 생성하기 전에 소문자 r을 붙이면 해당 문자열에서는 이스케이프 문자가 적용되지 않고 문자 그대로 출력된다.
print(r'"C:\Programs\python3\"')
# 결과
"C:\Programs\python3\"
- 경로를 입력하는 데에 주로 사용한다.
멀티라인 출력
multi = \
"""
문자열
멀티라인
테스트
"""
- 위와 같이 입력하면 형식 그대로 출력된다.
- 변수를 선언할 때
\
를 입력하면 엔터를 친 후에도 내용이 있다는 것을 파이썬에게 알려준다.
문자열 연산
str_o1 = "Niceman"
str_o2 = "Orange"
print(3 * str_o1)
print(str_o1 + str_o2)
print('i' in str_o1)
print('e' not in str_o2)
- 문자열에 숫자를 곱하면 해당 숫자만큼 문자열이 반복되어 출력된다.
- 문자열에 문자열을 더하면 두 문자열이 이어져서 출력된다.
- in 연산자와 not in 연산자를 사용해서 해당 문자가 문자열에 있는지 boolean 값으로 반환할 수 있다.
문자열 형변환
- str(x) 함수를 사용하면 x의 타입이 문자열로 변환된다.
문자열 함수
- 문자열과 관련된 함수를 사용해서 문자열을 변환할 수 있다.
- 문자열.capitalize() : 문자열의 앞 글자를 대문자로 바꾼다.
- 문자열.endswith(“a”) : 문자열이 a로 끝나면 True 아니면 False를 반환한다.
- 문자열.join([“첫문자열”, “둘째문자열”]) : 문자열의 앞과 뒤에 문자열을 더한 결과를 반환한다.
- 문자열.replace(‘첫문자열’, ‘둘째문자열’) : 문자열에 첫문자열과 같은 문자열이 있다면 그것을 둘째문자열로 치환한다.
- 문자열.replace(‘첫문자열’, ‘둘째문자열’, 숫자) : 위와 동일하지만 해당 숫자만큼까지만 치환한다.
- 문자열.split(‘ ‘) : 파라미터 값과 타입과 값이 같은 문자가 있을 때마다 나눠서 리스트로 반환한다.
- 문자열.list(reversed(문자열)) : 문자열을 문자로 나눠서 역순으로 반환한다. 리스트로 형변환 해줘야 한다.
- 문자열 함수 문서
문자열 슬라이싱
- 문자열을 수정이 불가능하다. immutable
str_sl = 'Niceboy'
print(str_sl[0:3])
print(str_sl[:len(str_sl)])
print(str_sl[:len(str_sl) - 1])
print(str_sl[:])
print(str_sl[1:4:2])
print(str_sl[-3:6])
print(str_sl[1:-2])
print(str_sl[::-1])
print(str_sl[::2])
# 결과
Nic
Niceboy
Nicebo
Niceboy
ie
bo
iceb
yobeciN
Ncby
- 문자열 뒤에 대괄호를 이용해서 범위를 지정한다.
- 앞 숫자는 포함, 뒷 숫자는 이전까지만 범위에 지정된다.
- 앞 숫자를 생략하면 0부터 시작한다.
- 앞 뒤 모두 생략하면 전 범위를 출력한다.
- [1:4:2]는 1번 인텍스부터 4번 인덱스 전까지 출력하되, 2칸씩 띄워 건너서 인덱스를 골라 출력한다는 뜻이다.
- 앞에서 -숫자를 지정하면 해당 숫자만큼 문자를 제외하고, 뒤에서도 마찬가지로 제외하고 출력한다.
- [::-1]은 모두 출력하되 역순으로 출력한다는 뜻이다.
- [::2]는 모두 출력하되 2칸씩 인덱스를 건너서 출력한다.
0615
테스트 2차 준비 2일차
기말고사와 함께 테스트를 준비하려니 너무 타이트하고 힘들다.
수요일이 지나야 조금 숨통이 틀 거 같다는 생각이 든다.
방금 테스트를 보고 왔는데, 코딩 문제를 아쉽게 못 풀고 3분뒤에 문제를 풀었다.
너무 아쉽다는 생각과 동시에 더 열심히 해야겠다는 생각이 들었다.
내일은 더 열심해 해서 다 맞을 수 있도록 노력해야겠다.
리스트
- 순서가 있고, 중복이 가능하다.
- 수정과 삭제가 가능하여 많이 사용된다.
선언
a = []
b = list()
c = [1, 10, 'a']
- 주로 대괄호를 이용하여 선언한다.
- 타입을 혼용하여 같은 리스트에 선언할 수 있다.
- 리스트안에 리스트를 중첩하여 선언할 수 있다.
인덱싱
- 리스트의 인덱싱은 문자열에서처럼 0번 인덱스부터 시작해서 1씩 증가한다. 우측부터 접근시 -1부터이다.
- 중첩 리스트에 접근하고 싶을 때는 2차원 배열 형태로 접근하면 된다. ex) a[0][2]
- 슬라이싱도 문자열과 비슷한 방법으로 사용하고 적용된다.
연산
- 리스트와 리스트를 더하면 하나의 리스트로 합쳐지고 내부의 값은 이어진다.
- 리스트에 숫자를 곱하면 해당 숫자만큼 리스트가 이어져서 하나의 리스트로 출력된다.
수정, 삭제
c = [1, 2, 3, 4]
c[0] = 77
print(c)
c[1:2] = ['a', 'b', 'c']
print(c)
c[1] = ['a','b','c']
print(c)
c[1:3] = []
print(c)
del c[1]
print(c)
# 결과
[77, 2, 3, 4]
[77, 'a', 'b', 'c', 3, 4]
[77, ['a', 'b', 'c'], 'b', 'c', 3, 4]
[77, 'c', 3, 4]
[77, 3, 4]
- 리스트 값의 수정은 해당 인덱스에 값을 덮어쓰면 된다.
- 다만 덮어쓰는 값이 리스트일 때는 중첩 리스트로 값이 수정된다.
- 덮어쓰는 값이 리스트고, 인덱스 범위지정을 슬라이싱을 이용해서 하면 중첩 리스트가 아닌 이어진 값으로 수정된다.
- 삭제하는 방법은 인덱스 범위지정을 슬라이싱해서 빈 대괄호를 입력하는 것과, del를 사용하는 방법이 있다.
함수
a = [5, 2, 3, 1, 4]
a.append(6)
print(a)
a.sort()
print(a)
a.reverse()
print(a)
a.insert(2, 7)
print(a)
a.remove(1)
print(a)
b = a.pop()
print(b)
print(a)
ex = [8,9]
a.extend(ex)
print(a)
print(a.index(4))
print(a.count(9))
#결과
[5, 2, 3, 1, 4, 6]
[1, 2, 3, 4, 5, 6]
[6, 5, 4, 3, 2, 1]
[6, 5, 7, 4, 3, 2, 1]
[6, 5, 7, 4, 3, 2]
2
[6, 5, 7, 4, 3]
[6, 5, 7, 4, 3, 8, 9]
3
1
append(x)
: 리스트의 끝에 x 값을 삽입pop()
: 리스트 끝에 있는 값을 꺼내고, 그 값을 반환insert(x, y)
: x 인덱스에 y 값을 삽입. 그 뒤에 값들은 한 칸씩 밀림remove(x)
: x 값을 리스트 앞에서부터 찾아서 찾으면 한 개만 삭제. del은 인덱스로 삭제한다면 remove는 값으로 삭제extend(x)
: 리스트 x를 기존 리스트에 이어서 값을 삽입. append의 매개변수 값으로 리스트를 삽입한다면 중첩 리스트로 삽입된다는 것이 차이점sort()
: 값을 오름차순으로 정렬reverse()
: 값을 내림차순으로 정렬index(x)
: x를 리스트에서 찾아서 존재한다면 x의 인덱스 값을 반환. 없다면 에러count(x)
: 리스트에 존재하는 x의 개수 반환
튜플
- 순서가 있고, 중복이 가능하다.
- 리스트와의 가장 큰 차이점은 수정 및 삭제가 되지 않는다는 점
- 인덱싱과, 연산은 리스트와 사용법이 같다.
- 함수는 index와 count 정도만 사용 가능하다.
선언
a = ()
b = (1,)
c = (1, 2, 3, 4)
d = (10, 100, ('a', 'b'))
- 리스트는 대괄호로 선언한다면, 튜플은 소괄호로 선언한다.
- 튜플 역시 중복 튜플이 가능하다.
딕셔너리
- 키와 값으로 구성되어 있다.
- 순서도 존재하지 않고, 키의 중복도 불가능하다.
- Json 형태와 비슷하다.
선언
a = {'name': 'Kim', 'Phone': '010-1234-1234', 'birth': 870214}
b = {0: 'Hello Python', 1: 'Hello Coding'}
c = {'arr': [1,2,3,4,5]}
- 중괄호로 선언하고, 키: 값 형태로 선언한다.
- 키를 숫자형으로 선언할수도 있지만 잘 사용하지는 않는다.
- 값으로는 문자열 말고도 숫자나 리스트, 튜플 모두 가능하다.
출력
print(a['name'])
print(a.get('name'))
- 값을 받는 두 가지 방법이 있는데, 인덱스처럼 안에 키를 넣어서 받는 방법과 get() 메소드를 사용하는 방법이 있다.
- 하지만 첫 번째 방법의 경우 해당하는 키가 없을 경우 에러를 반환하고, get() 메소드는 None을 반환하기 때문에 두 번째 방법이 안전하다는 이유로 더 많이 사용된다.
딕셔너리 추가
a['새로운키'] = 값
형식으로 간단하게 추가할 수 있다.
keys, values, items
print(a.keys())
print(a.values())
print(a.items())
# 결과
dict_keys(['name', 'Phone', 'birth'])
dict_values(['prak', '010-1234-1234', 870214])
dict_items([('name', 'prak'), ('Phone', '010-1234-1234'), ('birth', 870214)])
- keys(), values(), items() 메소드를 사용해서 딕셔너리 안의 키, 값, 키 값 쌍을 모두 꺼내올 수 있다.
- list() 메소드로 리스트로 형변환해서 주로 사용한다.
- items()의 경우 리스트로 형변환하면 리스트 안에 튜플로 키, 값이 묶여서 반환된다.
집합
- 순서가 없고, 중복도 없다.
선언
a = set()
b = set([1, 2, 3, 4])
- 집합은 set메소드 안에 리스트 형식으로 값을 넣는 방식으로 선언한다.
- 주로 리스트나 튜플처럼 다른 것으로 변환해서 사용한다.
집합 자료형 활용
s1 = set([1,2,3,4,5,6])
s2 = set([4,5,6,7,8,9])
print(s1 & s2)
print(s1.intersection(s2))
print(s1 | s2)
print(s1.union(s2))
print(s1 - s2)
print(s1.difference(s2))
# 결과
{4, 5, 6}
{4, 5, 6}
{1, 2, 3, 4, 5, 6, 7, 8, 9}
{1, 2, 3, 4, 5, 6, 7, 8, 9}
{1, 2, 3}
{1, 2, 3}
- 각각 교집합, 합집합, 차집합을 뜻한다.
추가 & 제거
add(x)
: x를 집합에 추가한다. 중복은 허용하지 않는다.remove(x)
: x 값을 찾아서 제거한다.
흐름 제어
조건문
기본 형식
if True:
# 이 줄이 실행. 들여쓰기 중요
if False:
# 출력되지 않음
if False:
# 여기는 실행되지 않음
else:
# 여기가 실행
- Boolean의 조건으로는 관계연산자도 올 수 있다.
참 거짓 종류
- 참 : “내용”, [내용], (내용), {내용}, 1
- 거짓 : “”, [], (), {}, 0, None
논리 연산자
a = 100
b = 60
c = 15
print(a > b and b > c)
print(a > b or c > b)
print(not a > b)
# 결과
True
True
False
- 산술, 관계, 논리의 우선순위는 산술 > 관계 > 논리 순서이다.
다중 조건문
if 조건1:
# 조건1에 부합하면 실행
elif 조건2:
# 조건1에는 맞지 않지만 조건 2에 부합하면 실행
else:
# 조건1,2에 맞지 않으면 실행
중첩 조건문
- 조건문 내에 조건문이 들어간 케이스
- 들여쓰기로 구분을 잘 해야 한다.
반복문
기본 반복문 사용(while, for)
# while
v = 1
while v < 11:
# v 가 11보다 작을동안 계속 반복
# 증감식을 써줘서 무한루프를 벗어나도록 해야함
# for
for v in range(10):
# v가 10보다 작을 때까지만 계속 반복. v는 1씩 증가
for v in range(1, 11):
# v의 시작값과 끝값을 설정
for v in range(1, 11, 2):
# v의 시작값과 끝값, 그리고 몇 씩 증가시킬건지 설정
시퀀스(순서가 있는) 자료형 반복
- 순서가 있는 문자열, 리스트, 튜플과 그리고 집합, 딕셔내리
- iterable 리턴 함수: range, reversed, enumerate, filter, map, zip
for 담을변수명 in 시퀀스자료형변수:
# 시퀀스자료형변수의 개수만큼 반복해서 출력
- 문자열과 리스트, 튜플의 사용법은 비슷하지만 딕셔내리만 조금 차이점이 있다.
my_info = {
"name": "Kim",
"age": 33,
"city": "Seoul"
}
# 기본은 키 반환
for key in my_info:
print(key)
# 값 반환
for key in my_info.values():
print(key)
# 키, 값 반환
for k, v in my_info.items():
print(k, v)
break, continue
- break는 반복문 도중 더 이상 반복을 실행하지 않아도 되는 경우 입력하면 반복문을 빠져나가는 명령어이다.
- continue는 반복문 도중 끝까지 실행하지 않고 다음으로 넘어가야 하는 경우 사용하는 명령어이다.
for-else
numbers = [14, 3, 4, 7, 10, 24, 17, 2, 33, 15, 34, 36, 38]
for num in numbers:
if num == 33: # 45
print("found : 33!")
break
else:
print("not found : ", num)
else:
print("Not Found 39...")
- 파이썬에서는 for-else를 지원하는데, break로 for문을 빠져나가지 못하면 마지막에 else가 실행되는 구문이다.
0616
테스트 2차 준비 3일차
드디어 학교 기말고사를 모두 마쳤다.
테스트 2차 준비와 병행하려니 일정이 너무 타이트해서 힘들었다.
오늘까지만 잘 이겨내면 내일부터는 좀 더 여유롭게 테스트에만 집중할 수 있을 것 같다.
오늘 공부한 함수, 클래스, 상속 부분이 난이도도 있고 엄청 중요한 것 같아서 시험을 보는 데에 걱정이 된다.
내일부터는 틀리지 않기 위해서 더 오랜 시간 동안 꼼꼼히 학습해야겠다.
함수 및 람다
함수
정의 방법
def function_name(param):
# 함수 실행 내용 정의
# 실행
function_name()
- 함수를 선언하는 위치가 중요하다. 선언을 하기 전에 함수를 실행하면 에러가 발생
반환
def hello_return(world):
value = "Hello " + str(world)
return value
str = hello_return('python')
print(str)
# 결과
Hello python
- 함수는 결과값을 반환해줄 수 있다.
def func_mul1(x):
y1 = x * 2
y2 = x * 4
y3 = x * 6
return y1, y2, y3
val1, val2, val3 = func_mul1(6)
print(val1, val2, val3)
# 결과
12 24 36
def func_mul2(x):
y1 = x * 2
y2 = x * 4
y3 = x * 6
return (y1, y2, y3)
tup = func_mul2(4)
print(tup)
# 결과
(8, 16, 24)
- 위와 같이 결과값을 여러개 반환해줄 수 있다.
- 다중 결과를 튜플이나 리스트, 딕셔너리로 묶어서 반환해줄 수 있다.
*args
- 함수의 매개변수 앞에 *를 하나 붙이고 사용하면, 튜플 형태로 받는다. (이터레이터 가능)
- 매개변수가 몇 개일지 알 수 없을 때 사용하면 유용하다.
def args_func(*args):
for i, v in enumerate(args):
print(i, v)
args_func('Kim')
args_func('Lee', 'Park')
# 결과
0 Kim
0 Lee
1 Park
- enumerate() 함수는 interable한 객체의 인덱스를 출력하는 것을 도와준다.
**kwargs
- 함수의 매개변수 앞에 *를 두 개 붙이고 사용하면, 딕셔내리 형태로 받는다.
def args_func(**kwargs):
print(kwargs)
args_func(Kim='sang', Lee='jung')
# 결과
{'Kim': 'sang', 'Lee': 'jung'}
- 일반 매개변수는 함수를 호출할 때 꼭 작성해줘야 하지만, 가변인자인
*args
와**kwargs
는 있어도 되고 없어도 된다.
중첩 함수
def nested_func(num):
def func_in_func(num):
print(num)
print("in func")
func_in_func(num + 10000)
nested_func(10000)
# 결과
in func
20000
Hint
- 함수를 정의할 때 매개변수의 타입과 리턴 타입을 명시해줘서 힌트를 남길 수 있다.
- 힌트에서 작성한대로 타입을 입력하지 않아도 에러가 발생하지는 않는다.
def tot_length1(word: str, num: int) -> int:
return len(word) * num
print(tot_length1("i love you", 10))
람다식
- 함수를 간단하게 작성하는 방법으로 메모리가 절약되고, 가독성이 향상되며 코드가 간결해지는 장점이 있다.
- 함수는 객체가 생성되어 리소스(메모리)를 할당한다.
- 반면 람다식은 즉시 실행(Heap 초기화) -> 메모리 초기화
lambda_mul_func = lambda x: x * 10
print(lambda_mul_func(5))
def func_final(x, y, func):
print(x * y * func(10))
func_final(10, 10, lambda x: x * 1000)
# 결과
50
1000000
lambda 매개변수: 실행부
식으로 람다식을 사용할 수 있다.- 함수의 매개변수로 함수를 넣을 수 있는데, 그 때 람다식을 작성해서 넘기면 메모리를 절약할 수 있다. + 간편
클래스
클래스
- 네임스페이스 : 객체를 인스턴화 할 때 저장된 공간
- 클래스 변수 : 직접 사용 가능, 객체보다 먼저 생성
- 인스턴스 변수: 객체마다 별도로 존재, 인스턴스 생성 후 사용 가능
- 클래스와 인스턴스의 차이를 아는 것이 중요하다.
선언
class UserInfo:
def __init__(self, name):
self.name = name
user = UserInfo("Kim")
- 기본 선언 방법은
class 클래스명:
으로 선언하고 아래에 구현하는 것이다. - 클래스명은 보통 첫 글자를 대문자로 한다.
__init__
메서드는 객체가 생성될 때 자동으로 동작하는 메서드이다.- 클래스 내부의 메서드의 매개변수로 self를 삽입하면 인스턴스 메서드, 삽입하지 않으면 클래스 메서드가 된다.
- 인스턴스 객체를 생성하는 방법은
클래스명()
이다. 인스턴스객체변수.__dict__
로 해당 객체의 네임스페이스에 접근할 수 있다.
self
- self.변수는 인스턴스 변수를 나타내고 클래스명.변수는 클래스 변수를 나타낸다.
- 인스턴스 변수는 인스턴스 객체 별도의 값, 클래스 변수는 공유하는 값이다.
인스턴스객체변수.변수이름
으로 해당 인스턴스 객체의 변수값에 접근할 수 있다.인스턴스객체변수.클래스변수
로 클래스 변수에도 접근할 수 있다. 인스턴스 네임스페이스에 값이 없으면 클래스 네임스페이스에서 값을 찾는 원리이다.- 클래스 메서드를 사용하려면
클래스명.클래스메서드
로 접근해야한다.
상속
- 슈퍼클래스(부모클래스)로부터 서브클래스(자식클래스)로 상속을 받을 수 있다.
- 상속을 받으면 슈퍼클래스의 속성과 메소드를 사용 가능하다.
- 재사용성을 높이고 중복을 줄일 수 있는 것이 장점이다.
class Car:
"""Parent Class"""
def __init__(self, type, color):
self.type = type
self.color = color
def show(self):
print('Car Class "Show" Method!')
class BmwCar(Car):
"""Sub Class"""
def __init__(self, car_name, tp, color):
super().__init__(tp, color)
self.car_name = car_name
- 자식 클래스를 작성할 때 클래스명에 (부모클래스명)을 넣어주면 해당클래스를 상속받는다.
- 부모클래스의
__init__
에 접근하기 위해서 super()를 사용하였다. - 자식클래스의 변수로 부모클래스의 메소드에 접근할 수 있다.
- 부모클래스의 메서드 이름과 같은 메서드를 자식클래스에서 재정의하여 사용할 수 있다.
Inheritance Info
- 상속 정보를 리스트 타입으로 반환해준다.
- 복잡한 상속 관계를 알아볼 수 있도록 도와준다.
찾고자 하는 클래스.mro()
다중 상속
- 파이썬에서는 다중 상속을 지원한다.
class X():
pass
class Y():
pass
class A(X, Y):
pass
- 위와 같이 작성하면 클래스 A는 클래스 X와 Y를 모두 상속받는다.
모듈, 패키지
- 모듈은 필요한 기능을 모아놓은 것이고, 패키지는 모듈을 모아둔 것이다.
사용법
from pkg.fibonacci import Fibonacci
from pkg.fibonacci import *
from pkg.fibonacci import Fibonacci as fb
- from 뒤는 필요한 기능을 모아둔 파일의 경로이다.
- import는 해당 파일에 있는 클래스를 의미한다.
- import에 *를 사용해 모든 것을 받아올 수도 있지만 필요한 것만 import할 것을 권장한다.
- as 를 사용해 alias를 지정해서 사용할 수도 있다.
파일 읽기, 쓰기
- 읽기 모드 : r
- 쓰기 모드 : w (기존 파일 삭제)
- 추가 모드 : a (파일 생성 또는 추가)
파일 읽기
f = open('./resource/review.txt', 'r')
content = f.read()
print(content)
f.close()
- open함수를 사용해서 파일을 조작하는데, 첫 번째 매개변수에는 파일을 지정하고, 두 번째 매개변수에는 모드를 설정한다.
- 변수에 담아 변수.read()를 실행하면 파일의 내용을 반환한다.
- open함수를 실행한 후에는 꼭 close 함수를 실행해서 자원을 반환해줘야 한다.
with open('./resource/review.txt', 'r') as f:
c = f.read()
print(c)
- with을 사용해서 open 함수를 좀 더 쉽게 사용할 수 있다.
- 이렇게 했을 때 장점은 f를 close로 닫아주지 않아도 indent를 벗어나면 자동으로 반환해준다는 것이다.
with open('./resource/review.txt', 'r') as f:
for c in f:
print(c)
- f 자체가 iterable 하기 때문에 반복문으로 바로 출력할 수도 있다.
with open('./resource/review.txt', 'r') as f:
line = f.readline()
while line:
print(line)
line = f.readline()
- readline() 메서드는 한 줄 씩 읽는 메서드이다.
- while 문에서 line에 내용이 남아있을 때까지만 반복한다.
- readlines() 메서드는 전체를 읽은 후 라인 단위 리스트로 저장하는 메서드이다.
파일 쓰기
with open('./resource/test.txt', 'w') as f:
f.write('niceman')
with open('./resource/test.txt', 'a') as f:
f.write('niceman')
- 모드를 w로 하고 write 메서드를 호출한 뒤 매개변수로 문자열을 넣으면 해당 문서에 문자열이 삽입되어 생성된다.
- 모드를 a로 하고 write 메서드를 호출하면 매개변수안의 값이 test.txt에 추가된다.
with open('./resource/test.txt', 'w') as f:
list = ['Kim', 'Park', 'Lee']
f.writelines(list)
- writelines() 메서드를 호출하고 안에 리스트를 넣으면 리스트를 test.txt에 차례대로 작성한 파일이 생성된다.
with open('./resource/test.txt', 'w') as f:
print("TESTSET", file=f)
- open함수 안에서 print()함수 옵션으로 file=해당변수를 넣으면 print문이 콘솔에 찍히는 것이 아니라 파일에 작성된다.
0617
테스트 2차 준비 4일차
파이썬의 기초 문법이 얼추 끝나간다.
4일이라는 상당히 짧은 시간동안 한 언어에 대해 어느정도 개념이 생기다니 신기하다.
그만큼 익히기도 쉽고 사용하기도 쉬워서 코딩테스트를 준비하는데 확실하게 도움이 될 것 같다는 생각이 들었다.
오늘은 예외 처리와 외부 파일 접근, 그리고 db연동에 대해 학습하였다.
예외
- 예외는 에러를 뜻하며, 여러 종류의 에러들이 존재한다.
- 크게 문법적으로 문제가 있는 에러와 문법적으로 에러는 없지만 코드 실행 프로세에서 발생하는 런타임 에러가 있다.
- 항상 예외가 발생하지 않을 것으로 가정하고 먼저 코딩해야 하고, 런타임 예외 발생 시 예외처리를 권장한다. (EAFP 코딩 스타일)
에러의 종류
SyntaxError
- 잘못된 문법
print('test)
print('Hello'))
if True
pass
NameError
- 참조 변수 없음
a = 10
print(b)
ZeroDivisionError
- 숫자를 0으로 나누면 발생하는 에러
print(10 / 0)
IndexError
- 인덱스 범위를 오버할 때 발생하는 에러
x = [10, 20, 30]
print(x[3])
AttributeError
- 모듈, 클래스에 있는 잘못된 속성 사용시에 발생
ValueError
- 참조 값이 없을 때에 발생하는 예외
x = [1, 5, 9]
x.remove(100)
FileNotFoundError
- 파일 open시 없는 파일을 참조할 경우 발생
TypeError
- 자료형에 맞지 않는 연산을 수행할 경우
- ex) 리스트와 튜플의 덧셈연산을 하였을 때
예외 처리 방법
try:
# 예외가 발생할 가능성이 있는 코드
except 예외명:
# 예외명에 해당하는 예외 발생 시 실행 코드
# 여러 개를 연달아 작성 가능
# 좁은 범위에서 큰 범위로
else:
# try문에서 예외가 발생하지 않았을 경우 실행
finally:
# 예외가 발생하던 안하던 무조건 실행되는 코드
예외 발생시키기
- raise 키워드를 사용해서 예외를 발생
try:
a = 'Park'
if a == 'Kim':
print('pass')
else:
raise ValueError
- 파이썬 에러말고, 에러 발생을 원하는 상황에 에러를 발생시킬 수 있다.
외부 파일 읽기
CSV 파일
- MIME - text/csv
import csv
를 해줘야 한다.
with open('./resource/sample1.csv', 'r', encoding='euc-kr') as f:
reader = csv.reader(f)
next(reader)
for c in reader:
print(c)
- txt 파일과 마찬가지로 open 함수를 사용해서 파일을 읽는다.
- csv.reader(파일)로 반환된 결과를 변수에 담는다.
- 반환 결과는 iterable하기 때문에 반복문으로 출력하면 한 줄씩 리스트로 출력한다.
- next(반환결과)를 사용해서 사용 횟수만큼 앞줄이 제외되고 출력된다.
- csv 파일이 ,가 아니라
|
로 구분되어 있으면csv.reader(f, delimiter='|')
옵션을 사용해서 , 리스트로 반환해줄 수 있다.
with open('./resource/sample1.csv', 'r') as f:
reader = csv.DictReader(f)
for c in reader:
for k, v in c.items():
print(k, v)
csv.DictReader(f)
를 사용하면 딕셔내리로 반환해준다.
CSV 파일 쓰기
w = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15]]
with open('./resource/sample3.csv', 'w') as f:
wt = csv.writer(f)
for v in w:
wt.writerow(v)
wt.writerows(w)
- sample3.csv 파일을 생성하고 한 줄씩 작성한다.
- writerows 함수는 결과적으로는 writerow와 같다
XSL, XLSX
- MIME - applications/vnd.excel
- pip install pandas 설치 필요
- pip install xlrd 설치 필요
- pip install openpyxl 설치 필요
import pandas as pd
xlsx = pd.read_excel('./resource/sample.xlsx') # sheetname='시트명' 또는 숫자, header=3, skiprow=1 실습
# 상위 데이터 확인
print(xlsx.head())
# 데이터 확인
print(xlsx.tail())
# 데이터 구조
print(xlsx.shape) # 행, 열
# 엑셀 or CSV 다시 쓰기
xlsx.to_excel('./resource/result.xlsx', index=False)
xlsx.to_csv('./resource/result.csv', index=False)
DB
DB 연결
import sqlite3
conn = sqlite3.connect('원하는경로/database.db', isolation_level=None)
c = conn.cursor()
- sqlite3.connect()는 해당 경로에 db를 조회하고, 없으면 생성한다.
- isolation_level=None은 auto commit을 해주는 옵션이다.
- conn.cursor()은 커서를 연결해준다. 앞으로 c를 사용해서 db를 조작할 예정이다.
테이블 생성
- sqlite datatype
- text
- numeric
- integer
- real
- blob
c.execute("CREATE TABLE IF NOT EXISTS users(id INTEGER PRIMARY KEY, username text, email text, phone text, website text, regdate text)")
- users 테이블을 생성한다.
- 커서.execute 명령어로 sql을 작성한다.
데이터 삽입
c.execute("INSERT INTO users(id, username, email, phone, website, regdate) VALUES (?, ?, ?, ?, ?, ?)",
(2, 'Park', 'Park@naver.com', '010-1111-1111', 'Park.com', nowDatetime))
- 문자열이 아닌 변수를 sql에 삽입해야 하는 경우는 우선 변수를 삽입할 자리에 ?를 작성하고 sql이 마친 뒤
, ()
형식으로 삽입한다.
userList = (
(3, 'Lee', 'Lee@naver.com', '010-2222-2222', 'Lee.com', nowDatetime),
(4, 'Cho', 'Cho@naver.com', '010-3333-3333', 'Cho.com', nowDatetime),
(5, 'Yoo', 'Yoo@naver.com', '010-4444-4444', 'Yoo.com', nowDatetime)
)
c.executemany("INSERT INTO users(id, username, email, phone, website, regdate) VALUES (?, ?, ?, ?, ?, ?)", userList)
- 한 번에 여러 데이터를 삽입할 수 있는 executemany() 함수가 있다.
- 미리 중첩 리스트나 중첩 튜플로 삽입할 데이터를 정의해두고, 해당 변수를 입력하여 삽입한다.
데이터 조회
c.execute("select * from users")
print(c.fetchone())
print(c.fetchmany(size=2))
print(c.fetchall())
- 처음 데이터를 조회했을 때는 콘솔에 아무것도 찍히지 않는다.
- c.fetchone()은 현재 커서 위치에서 로우 하나를 반환한다.
- c.fetchmany(size=x)는 현재 커서 위치에서 로우 x개를 반환한다.
- c.fetchall()은 전체 로우를 반환한다.
- 커서 위치는 계속해서 변경된다.
c.execute("select * from users")
rows = c.fetchall()
for row in rows:
print(row)
for row in c.fetchall():
print(row)
for row in c.execute("select * from users"):
print(row)
- 위의 세 개 모두 각각 다른 순회 방법이다.
- 1번은 변수에 모두 검색하는 리스트를 저장한 뒤 반복문들 돌리는 것이고,
- 2번은 변수 대신 바로 집어넣은 것이다.
- 3번은 반복 대상에 바로 execute() 함수를 실행하여 순회한 것이다.
c.execute('select * from users where id=?', (1,))
print(c.fetchall())
c.execute('select * from users where id="%s"' % 1)
print(c.fetchall())
c.execute('select * from users where id=:Id', {'Id': 3})
print(c.fetchall())
- sql문에 변수를 넣는 방법에는 크게 3가지가 있다.
- ?와 , 튜플
- %s와 % 자료형
- :key와 , 딕셔내리
데이터 수정 및 삭제
c.execute("UPDATE users SET username = ? WHERE id = ?", ('niceman', 1))
c.execute("DELETE FROM users WHERE id = ?", (7,))
테이블 전체 데이터 삭제
Print(conn.execute("delete from users").rowcount)
- 테이블 데이터를 모두 삭제하고 삭제한 로우를 반환한다.
커밋, 롤백, 접속해제
# 커밋
conn.commit()
# 롤백
conn.rollback()
# 접속 해제
conn.close()
- 사용 후 자원을 반환해줘야 한다.
Dump 출력
- 데이터베이스 백업을 위해 사용
with conn:
with open('./resource/dump.sql', 'w') as f:
for line in conn.iterdump():
f.write('%s\n' % line)
- conn에 연결된 db가 dump.sql에 복사된다. (테이블 구조와 데이터 삽입 커밋까지)
- 자동으로 conn과 f는 자원 반환된다.
0614
테스트 2차 준비 5일차
한 주 동안 파이썬을 학습하였다.
기말고사와 병행하며 약 5일동안 학습했을 뿐인데, 한 언어에 대해 많이 배운 것 같아서 뿌듯한 한 주였다.
오늘 시험까지 잘 마무리 지어서 주말동안은 파이썬을 복습하고, 자료구조 강의로 넘어갈 준비를 해야겠다.
오늘은 지금까지 배운 것을 활용하여 미니 게임 프로젝트를 하고, 파이썬의 객체 참조와 deep copy에 대해서 학습하였다.
객체 참조
id vs __eq__
- id는 객체 주소 비교,
__eq__
는 값 비교 - is는 주소 비교 연산자, ==는 값 비교 연산자
x = [1,2,3,4]
y = x
x.append(5)
print(x, y)
print(x == y)
print(x is y)
print(x is not y)
x = [1, 2, 3, 4]
y = list(x)
x.append(5)
print(x, y)
print(x == y)
print(x is y)
print(x is not y)
# 결과
[1, 2, 3, 4, 5] [1, 2, 3, 4, 5]
True
True
[1, 2, 3, 4, 5] [1, 2, 3, 4]
False
False
- 리스트가 담긴 변수에는 리스트의 주소값이 담겨있기 때문에 그것을 다른 변수에 그대로 할당하면 제대로 복사가 되지 않고 둘은 같은 객체를 가르키게 된다.
- 해당 자료형을 생성하는 형변환을 해줘서 그 안에 값을 담아줘야 제대로 복사가 된다.
튜플 불변형의 비교
tuple1 = (10, 15, [100, 1000])
tuple2 = (10, 15, [100, 1000])
print('EX3-1 -', id(tuple1), id(tuple2))
print('EX3-2 -', tuple1 is tuple2)
print('EX3-3 -', tuple1 == tuple2)
print('EX3-4 -', tuple1.__eq__(tuple2))
# 결과
EX3-1 - 4481162240 4481568512
EX3-2 - False
EX3-3 - True
EX3-4 - True
- 원래 튜플은 불변형이어서 id 값이 같아야 하지만 내부에 서로 다른 id를 가진 리스트가 존재하기 때문에 튜플의 id 값도 달라진다.
tl1 = [10, [100, 105], (5,10,15)]
tl2 = tl1
tl3 = list(tl1)
print('EX4-1 -', tl1 == tl2)
print('EX4-2 -', tl1 is tl2)
print('EX4-3 -', tl1 == tl3)
print('EX4-4 -', tl1 is tl3)
tl1.append(1000)
tl1[1].remove(105)
print('EX4-5 -', tl1)
print('EX4-6 -', tl2)
print('EX4-7 -', tl3)
tl1[1] += [110, 120]
tl1[2] += (110, 120)
print('EX4-8 -', tl1)
print('EX4-9 -', tl2) # 튜플 재 할당(객체 새로 생성)
print('EX4-10 -', tl3)
# 결과
EX4-1 - True
EX4-2 - True
EX4-3 - True
EX4-4 - False
EX4-5 - [10, [100], (5, 10, 15), 1000]
EX4-6 - [10, [100], (5, 10, 15), 1000]
EX4-7 - [10, [100], (5, 10, 15)]
EX4-8 - [10, [100, 110, 120], (5, 10, 15, 110, 120), 1000]
EX4-9 - [10, [100, 110, 120], (5, 10, 15, 110, 120), 1000]
EX4-10 - [10, [100, 110, 120], (5, 10, 15)]
tl1[1].remove(105)
를 했을 때 tl3에서도 삭제되는데, 그 이유는 깊은 복사를 하지 않았기 때문에 모두 같은 id를 가지고 있기 때문이다.- 같은 이유로
tl1[1] += [110, 120]
를 했을 때 tl3에서도 추가되었다. - 반면,
tl1[2] += (110, 120)
를 했을 때는 tl1과 tl2에만 변화가 있는데, 튜플은 기본적으로 삭제가 불가능하기 때문에 삭제가 되는 것이 아니라 새로 객체를 생성하여 재할당하는 개념이다. 그래서 tl1과 id가 같은 tl2의 튜플만 같은 객체를 재할당해줘서 이런 결과가 나온다.
얕은 복사와 깊은 복사
- 얕은 복사는 객체의 id만 다르도록 복사하는 경우이다.
- 깊은 복사는 객체의 id 뿐만이 아니라, 객체가 가지고 있는 리스트나 튜플 등, 객체의 객체까지 모두 id가 다르도록 복사하는 것이다.
- 깊은 복사를 사용하기 위해서는 copy를 import 한 뒤
copy.deepcopy(복사할객체)
방식으로 사용한다.
함수 매개변수 전달 사용법
def mul(x,y):
x += y
return x
a = [10, 100]
b = [5, 10]
print('EX6-2 -', mul(a, b), a, b) # 가변형 a -> 원본 데이터 변경
c = (10, 100)
d = (5, 10)
print('EX6-2 -', mul(c, d), c, d) # 불변형 c -> 원본 데이터 변경 안됨
# 결과
EX6-2 - [10, 100, 5, 10] [10, 100, 5, 10] [5, 10]
EX6-2 - (10, 100, 5, 10) (10, 100) (5, 10)
- 가변형 데이터는 매개변수로 값을 넘길 때 주소의 값을 넘기기 때문에 원본 데이터가 변경된다.
- 불변형 데이터는 매개변수로 값을 넘겨서 수정하여도 원본 데이터가 변경되지 않는다.
파이썬 불변형 예외
- str, bytes, frozen set, Tuple은 사본을 생성하지 않고, 참조를 반환한다.
tt1 = (1, 2, 3, 4, 5)
tt2 = tuple(tt1)
tt3 = tt1[:]
print('EX7-1 -', tt1 is tt2, id(tt1), id(tt2))
print('EX7-2 -', tt3 is tt1, id(tt3), id(tt1))
tt4 = (10, 20, 30, 40, 50)
tt5 = (10, 20, 30, 40, 50)
ss1 = 'Apple'
ss2 = 'Apple'
print('EX7-3 -', tt4 is tt5, tt4 == tt5, id(tt4), id(tt5))
print('EX7-4 -', ss1 is ss2, ss1 == ss2, id(ss1), id(ss2))
# 결과
EX7-1 - True 4478616336 4478616336
EX7-2 - True 4478616336 4478616336
EX7-3 - True True 4479509504 4479509504
EX7-4 - True True 4480468720 4480468720
0619 ~ 0620
평일동안 열심히 코딩테스트를 준비하고, 주말에는 휴식 시간을 가졌다.
학교 공부랑 겹쳐서 꽤나 힘든 일정이었다.
내일부터는 드디어 자료구조를 시작한다.
주말동안 푹 쉬었으니 또 열심히 달려봐야겠다.