1. 주석
- 한 줄 주석:
#
- 여러 줄 주석
- 문자열을 만드는 방법과 동일하게
""" 내용 """
or''' 내용 '''
사이에 넣을 수도 있지만 - PEP8에선 한 줄짜리 주석을 연속해서 쓰는 것을 권장하고 있다.
- 서브라임 텍스트 등 대부분의 에디터는
cmd(or ctrl) + /
단축키를 지원한다.
- 문자열을 만드는 방법과 동일하게
2. 자료형
2.1. 숫자형
항목 | 사용 예 |
---|---|
정수 | 123, -123, 0 |
실수 | 1.2, -0.4, 3.4e10 |
복소수 | 1+2j, -3J |
8진수 | 0o45, 0O42 |
16진수 | 0xA1, OXFF |
- 지수 표현하기: 1의 자리 수와 소수로만 표현한다. 그리고 뒤에
e
(E 동일)를 붙여서 10의 제곱수를 곱해서 표현한턴.1.23e10
은 1.23에 10의 10승을 곱한 것이고,3.45e-10
은 3.45에 10의 -10승을 곱한 것이다. - 복소수 활용: 내장함수가 있다.
복소수.real
,복소수.imag
처럼 뒤에 붙여 사용하면 순서대로 실수부와 허수부를 리턴한다.복소수.conjugate()
라는 내장함수를 사용하면 켤레복소수를 리턴한다.abs(복소수)
는 절대값을 리턴하는데 계산 방식은1+2j
일 때 1의 제곱과 2의 제곱을 더해서 루트씌운것이다.
2.2 문자열
2.2.1 기본
- 문자열 나타내는 방법:
''
,""
,''' '''
,""" """
이렇게 4가지다. - 문자열 합칠 때: 더하면 된다.
"hihi" + "hello"
=>"hihihello"
- 문자열 반복시키기: 곱하면 된다.
"hi" * 2
=>"hihi"
- 문자열 역시 iterable이다. 인덱싱과 슬라이싱 활용할 수 있다.
'abc'[2]
=>'c'
,'abcde'[-1]
=>'e'
,'abc'[-0]
=>'a'
'abc'[:2]
=>'abc'
,'abcde'[1:3]
=>'bcd'
,'abcde'[1:-2]
=>'bc'
- 하지만 인덱싱을 활용해서 문자열의 내용을 바꿀 수는 없다.
'abc'[0] = 'A'
를 하려면 에러가 뜬다. 새로 만들어야 한다. 기존 것을 활용하고 싶다면 바꾸고 싶은 글자의 인덱스를 확인하여 전과 그 후 부분을 슬라이싱해서 이어붙이면 된다. - :을 기준으로 start, end, stride 다. 만약 stride가 -면 뒤에서부터 역순으로 밟아나간다 생각하면 된다.
'abc'[::-1]
이면'cba'
이고,'abc'[::-2]
이면'ca'
이다.
2.2.2 문자열 포매팅
코드 | 설명 |
---|---|
%s | 문자열 String |
%c | 문자 character |
%d | 정수 Integer |
%f | 부동 소수 floating-point |
%o | 8진수 |
%x | 16진수 |
%% | 퍼센트 문자 나타내기 |
'%d %s + %'
사용 방법"I eat three %s" % "apple"
"I eat %d %s" % (3, "apple")
“I eat %s apples” % 3
이렇게 하면 3이 문자열 형태로 치환돼서 들어감. 변수가 무슨 타입인지 모르면 그냥%s
로 다 받아도 상관없다.- 값을 나타내는 변수를 활용해도 된다.
- %를 사용할 때
%
문자를 나타내려면%%
두 번 적어야 한다.%d%%
%10s
우측정렬.%-10s
좌측정렬. 공백 10개%.4f
소수점 4자리까지
format
사용 방법"{0} is {1}".format(1, “hi”)
- 역시 % 때와 마찬가지로 숫자는 문자열로 자동 변환되고 값이 아닌 변수를 활용해도 오케이.
- 이름으로 치환 가능하고 혼용도 된다:
“I ate {0} applse. so I was {sick}”.format(3, sick=“hi”)
- format에서 정렬하기
{0:<10}
좌측 정렬,{0:>10}
우측 정렬,{0:^10}
가운데 정렬 10칸 공백- 정렬기호(<, >, ^) 앞에 문자 하나 넣으면 그걸로 빈칸 채움.
{0:_^10}
이런 식
- .format에서 소수점 표현:
{0:10.4f}
- .format에서 curly bracket
{ }
를 문자 그 자체로 표현하려면 2번 써준다.{{ }}
- 문자열 앞에
r
을 붙여서r'hello'
이렇게 쓰면 순문자열이 된다. 즉 excape 문자\
를 쓰지 않아도\n
이나\t
같은 문자를 나타낼 수 있다.
2.2.3 주요 함수들
- 문자열에서 특정 문자 개수 세기:
a = ‘hobby’
,a.count(‘b’)
- 문자열에서 특정 문자 위치:
a.find(‘b’)
또는a.index(‘b’)
- 문자열 삽입 join:
“,”.join(‘abcd’)
를 하면“a,b,c,d”
가 된다. - 공백 지우기:
a.lstrip()
,a.rstrip()
왼쪽 오른쪽 지우기. 양쪽은 그냥strip()
- 문자열 바꾸기
replace
. 정규표현식 간편하게 만든 느낌이다.a = “life is too short”
a.replace(“life”, “yours”)
a = “yours is too short”
가 됨
split()
. 나눠서 리스트에 넣음()
사이에 아무것도 안넣으면 공백 기준으로 구분함a=“a:b:c:d”
일 때a.split(“:”)
하면[‘a’, ‘b’, ‘c’, ‘d’]
str.maketrans(x[, y[, z]])
: 문자 단위 매핑되는 사전을 만드는 것- 매개변수 한 개: dictionary 객체
- 두 개: 동일한 길이의 두 문자열이 들어가서 같은 위치끼리 대치된다.
- 세 개: 앞의 두 매개변수는 두 개일 때와 같고, 세 번째 문자열은 모든 문자가 None으로 매핑된다.
'Hello world!'.translate(dict_obj)
: maketrans 함수로 나온 dict 객체를 규칙으로 해서 문자열을 변환한다.
2.3 리스트
2.3.1 기본
- 리스트에 다양한거 다 들어갈 수 있다. 리스트까지 들어갈 수 있음.
- 빈 리스트 생성은
a = list()
ora = []
- 리스트의 리스트는 이차원배열처럼 이해하면 됨. 리스트의 리스트의 리스트는 당연하게도 삼차원배열처럼 뽑아냄
- 리스트 슬라이싱. 문자열 슬라이싱과 동일
- 리스트 더하면 합쳐진 리스트가 됨. 곱하기는 같은게 반복되서 리스트가됨.
- 리스트 수정은 그 부분 뽑아서(요소 하나만 인덱스로 뽑든, 슬라이싱으로 뽑든) 다른거 대입하면 된다. 리스트를 집어넣으면 리스트가 들어간다. 다만 한 가지 다른 것은
a[0] = [1, 2, 3]
으로 하면 리스트 자체가 들어가게되고a[0:1] = [1, 2, 3]
으로 하면 첫 칸에 요소 세 칸이 들어가는 것. 리스트가 들어가는게 아니다.
- 리스트 요소 삭제는
a[0]=[]
,a[1:3]=[]
식으로 빈 리스트를 대입하면 된다. 혹은 del 함수를 사용해서del a[0]
해도 된다. del 하면 객체 자체가 지워진다. 즉 사용하던 메모리를 free 시킨다는 것을 의미한다. 즉 garbage collection이며 파이썬이 자체적으로 하고 있기 때문에 메모리 사용량을 위해 굳이 따로 해줄 필요는 없다.
2.3.2 관련 함수들
리스트 + 리스트 하면 두 리스트가 연결된다.
[1] * 5
를 하면[1, 1, 1, 1, 1]
이 된다. 초기값 세팅할 때 좋을듯. 다음 예는 5X5 이차원 배열에 문자 'O'를 세팅하는 예다.board = [] for i in range(5): board.append(["O"]*5)
a.append('something')
요소 추가는 맨 마지막에 붙는다.a.sort()
는 요소를 순서대로 정렬하는 것. 숫자도 되고, 문자도 된다. 오름차순.a.reverse()
는 요소 순서를 반대로 바꾸는거. 즉 sort한 다음에 리버스하면 내림차순 정렬이 됨.a.index(요소)
를 하면 인덱스값을 반환.a.insert(index, value)
를 하면 대체가 아니라 추가가 된다. 0 인덱스에 넣으면 원래 있던 요소들이 앞으로 한 칸씩 밀린다. 즉 설정한 인덱스 이후의 요소들이 모두 한칸씩 뒤로 밀린다.a.remove(value)
를 하면 a의 요소들 중 첫 value 요소를 제거한다. 만약 요소가 없다면 에러가 난다. 모든 요소를 다 제거하고 싶으면 try 안에 반복문 돌리는 것도 괜찮겠다.a.pop()
은 맨 마지막 요소 빼낸다. 매개변수로 인덱스 값을 넣어주면 remove와 똑같이 첫 요소를 제외한다. 다만 remove와 다른 점은 뽑은 값을 리턴한다는 것.a.count(1)
은 1이 몇 겐지 세아려서 갯수를 리턴함a.extend([1,2,3])
을 하면 a 리스트 뒤에 매개변수 값이 합쳐진다.a += [1, 2, 3]
과 동일한 의미다. append와 다른 점은 만약a.append([1, 2, 3])
하면 a의 마지막에 리스트 자체가 원소로 들어간다. 리스트가 합쳐지는게 아니라 리스트가 붙는다. 즉 위의 리스트 수정에서 extend는 슬라이싱, append는 인덱싱과 매칭된다 할 수 있다.
2.4 튜플
- 리스트와 대부분 쓰는 방법이 같다. 생성은
my_tuple = ()
를 쓰는 것이 일반적이고 아예 안써도 된다. 예를 들어a = 1, 2, 3
처럼. - 위처럼 적용되기 때문에 리스트 내포 for문을 사용할 때
[]
로 감싸주지 않고도 바로 sum이나 max 함수를 쓸 수 있는 것이다. - 수정이 불가능하다. 상수화 된 리스트라고 생각하면 될까. 이 특성이 가장 중요하다. 대부분의 메소드를 똑같이 쓸 수 있지만 수정, 삭제, 추가는 안된다.
- 요소 한 개만 쓰려면
a = (1,)
이렇게 뒤에 콤마 붙여야 함
2.5 딕셔너리
2.5.1 기본
a = {‘key’:’value’, ‘key’:’value’}
- 키와 밸류로 이루어짐. 키를 인덱스처럼 활용해서 밸류를 뽑아낼 수 있다.
- 키에는 숫자도 되고 문자열도 됨. 튜플도 됨. 하지만 리스트는 안됨. 키에는 변하는 값이 들어가면 안된다. 밸류에는 어떤 값이든 다 됨
- 딕셔너리에는 인덱싱이나 슬라이싱 안된다. 무조건 키를 인덱스처럼 활용해서 밸류를 뽑아내는 수밖에 없다.
- 뽑아내는거랑 같은 방식으로 썼을 때 만약 그 쌍이 없다면 추가되는 것.
- 딕셔너리에는 순서가 없음.
- 삭제는
del a[key]
형태로. - 처음 딕셔너리를 생성할 때
{1:111, 1:222}
형태로 키를 중복시키면 랜덤으로 하나만 남는다. 뭐가 없어지고 남을지 모른다. - 딕셔너리도
len(dict)
먹힌다. key-value pair 개수를 리턴.
2.5.2 관련 함수
a.keys()
라고 하면 딕셔너리의 키들이 뽑혀나옴. dict_keys 라는 객체 형태로 뽑힘. 만약 리스트가 필요하다면list(a.keys())
로 형변환하면 됨. 근데 굳이 변환 안해도 반복문 쓸 수 있음.- dict_keys 객체에선 append, insert, pop, remove, sort 메소드 사용 안된다.
a.values()
라고 하면 dict_values 객체가 리턴됨. 키객체와 같음a.items()
를 하면 쌍을 튜플로 각각 묶어서 dict_items 객체로 리턴함- 다 지우려면
a.clear()
a[key]
와 비슷하게a.get(key)
도 됨. 다른 점은 없는걸 원했을 때 전자는 에러를 띄우지만 후자는 NONE을 출력. 후자가 나은듯. 에러 없으니a.get(key)
를 쓸 때 만약 값이 없을 때 논 대신 다른걸 쓰려면 디폴트값 설정할 수 있다. 이렇게.a.get(key, default)
- key가 있는지 조사할 때
key in my_dict
쓰면 된다. 사실in
은 리스트나 튜플, 문자열 등에서도 모두 쓰일 수 있다. True False 리턴한다.
2.6 집합(Sets)
- set은
my_set = set(my_list)
형태로 만든다.my_set = set([1,2,3,4,5,5,5,5,5])
=>set([1, 2, 3, 4, 5])
my_set2 = set(‘hello’)
=>set([‘h’, ‘e’, ‘l’, ‘o’])
- 중복도 없고 순서도 없다.(index 미지원)
list(my_set)
처럼 형변환해서 인덱스 써라.- 교집합:
&
또는set1.intersection(set2)
- 합집합:
|
또는set1.union(set2)
- 차집합:
set1 - set2
또는set1.difference(set2)
- 집합에 추가할 때
- 한개만 추가:
set1.add(value)
- 여러개 동시 추가:
set.update([5,6,7])
- 한개만 추가:
- 제거:
set.remove(value)
이것도 매개변수 딱 하나만 받는 함수다. - 세트의 원소로 리스트, 세트, 딕셔너리는 들어갈 수 없다. unhashable type이라고 TypeError라고 뜬다.
2.7 Boolean
- 문자열, 리스트, 튜플, 사전형, 세트가 차있으면 참. 비어있으면 거짓
a = [1, 2, 3, 4]
일 때 a 리스트를 조건으로 해서 pop으로 뽑아내면 모두 뽑힌다. 예를 들어while(a): print(a.pop())
대신 이렇게 하면 반복이 끝난 후 a는 빈 리스트가 된다.
2.7 변수에 대하여
(a, b) = 1, 2
혹은[a, b] = [3, 4]
식으로 여러 변수에 값을 한 방에 대입할 수 있다.- 두 변수의 값을 swap 하는 재밌는 방법:
a, b = b, a
- list를 복사할 때는 단순히
b = a
처럼 대입하면 안된다.- 두 레퍼런스 변수가 같은 객체를 가리키는 것이 되어버린다. 동일한 놈을 가리키고 있음.
- 이러면 a가 가리키는 list의 원소를 수정했을 때 b가 가리키는 list의 원소도 변한다. 같은 list니까.
b = a[:]
처럼 하거나from copy import copy
한 후에b = copy(a)
처럼 활용한다.
3. 제어문(if, while, for)
value in iterable
형태 잘 쓰임.value not in iterable
도 가능.is
와==
는 같은 의미. 동시에is not
과!=
역시 같은 의미조건문에서 아무것도 하기 싫으면
pass
사용. 아예 안적으면 오류나서 이거 적어줘야 한다.가장 가까운 반복문 빠져나가는
break
반복문에서 아래 코드는 더 이상 실행하지 않고 다음 반복으로 넘어가는
continue
리스트 내포:
[표현식 for 항목 in 반복가능객체 if 조건문]
for문에서 2개씩 변수를 받을 수도 있다.
- 근데 만약 변수를 하나로만 받으면 아래 코드의 케이스에서
[1,2] [3,4] [5,6]
이렇게 세 뭉치로 튀어나오고 - 변수를 i, j, k 세 개로 받으면 2개밖에 없는데 왜 3개 지정했냐고 에러가 난다. (루비에서는 알아서 k에 None을 넣더라. 에러 없이)
test_list = [[1, 2], [3, 4], (5, 6)] for i, j in test_list: print(i, j)
- 근데 만약 변수를 하나로만 받으면 아래 코드의 케이스에서
print는 자동으로 개행한다. 없애려면
print("somethin", end=" ")
식으로 end에 원하는 문자를 지정해주면 된다. 디폴트가 개행문자\n
인 셈이다.for
와while
에서else
를 같이 쓸 수 있다.- 조건에 맞게 반복을 돈 후, 빠져나올 때 else의 실행문을 한 번 실행한다.
- 하지만 조건이 아니라 중간에서
break
때문에 빠져나올 경우엔 else를 실행하지 않는다. - 리스트에서 조건 검사를 할 때 온전히 통과했다는 메시지를 else를 통해 해줄 수 있겠다. 만약 중간에서 틀린 검사가 나와서 break 했을 경우엔 else가 실행되지 않으므로 통과 메시지가 출력되지 않는다.
zip
: 리스트가 2개 있는데 매칭해서 출력하고 싶을 때 사용한다. 짧은 쪽 리스트가 끝날 때 반복이 멈추고 원하는 만큼 리스트들을 zip할 수 있다.list_a = [3, 9, 17, 15, 19] list_b = [2, 4, 8, 10, 30, 40, 50, 60, 70, 80, 90] for a, b in zip(list_a, list_b): print max(a, b)
4. 입출력
4.1 함수
함수 정의할 때 매개변수 없더라도 빈 괄호를 붙여줘야 한다.
def hi(): print("HI")
def
라인 바로 아래에는 주석으로 함수에 대한 설명을 적어주면 좋다.함수를 정의할 때 다른 함수 활용 가능. 즉 함수 내에서 함수 호출 가능
함수의 리턴값은 오직 하나다. 두 개 이상을 리턴하는 것으로(예로
return a, b
) 함수가 짜여진다면 이것은(a,b)
라는 하나의 튜플이 리턴되는 형태다. 그래서c, d = a()
이런식으로 바로 두 개 변수에 집어넣을 수 있음.매개변수로 몇 개를 받을지 모를 때 앞에
*
붙여주면 된다. 주로*args
라고 칭하는게 컨벤션이고 원하면 args 말고 다른 단어(python)를 써도 된다. 마지막에 써줘야 함. 이 args를 쓰려면 튜플 형태로 매개변수가 들어오기 때문에 iterable 활용하는 방식으로 써주면 된다.매개변수가 입력되지 않았을 때 디폴트값(초기값)을 설정할 수 있다. 매개변수 뒤에
param=value
하면 된다. 대신 디폴트값이 없는 매개변수 뒤에 있어야한다.함수 내의 변수 효력 범위
- 아래 코드처럼 함수를 실행해도 a의 값은 변하지 않는다.
- 정말 단순히 함수 내의 지역변수일 뿐이다. 값만 전달받은 것 뿐(call by value), 그 값 자체를 변화시키지(call by reference) 않는다.
- 1을 증가시킨 값을 리턴해서 원래 변수에 다시 대입하는 방식밖에 없다.
a = 1 def variable_test(n): n += 1 return variable_test(a) # a doesn't change
4.2 입력과 출력
- print에서
print('hi' 'hi' 'hi')
처럼 붙여쓰면+
랑 똑같고, - comma(,)로 이으면 띄워써진다.
print(‘hi’, ‘hi’, ‘hi’)
- 사용자 입력은
input()
해주면 된다. 리턴값은 입력받은 값이고, 매개변수로 문자열을 넣으면 콘솔에"입력하세요: "
이런 문구로 사용된다. 무조건 문자열 타입 리턴
4.3 파일 읽고 쓰기
4.3.1 파일 스트림 열고 닫기
아래 코드가 가장 일반적인 포맷이다. 즉
파일객체 = open(파일이름, 모드)
형태.모드는 r, w, a가 있고 순서대로 읽고, 쓰고, 추가한다. r+를 넣으면 read, write 둘 모두 된다.
# 디렉토리에서 ~ 단축키는 안 먹힌다. 절대경로 쓰려면 다 적어줘야 함 f = open("/Users/gyubin/Desktop/hi.txt", 'w') f.close()
4.3.2 읽기 함수
f.read()
: 파일의 모든 데이터를 읽어온다. 모든 데이터를 읽어왔다면 다시 이 함수를 실행했을 때 빈 문자열""
을 리턴한다.f.read(int_value)
: 숫자크기 만큼만 글자를 읽어온다. 3을 넣으면 3글자씩 읽어온다. 실행할 때마다 정한 크기만큼 글자를 읽어오고 모두 읽어왔을 때는 역시 빈 문자열""
를 리턴한다.f.readline()
:\n
이 발견될 때까지 개행문자를 포함해서 읽어온다. 즉 한 줄씩 읽어온다. 파일이 개행문자 없이 끝난다면 파일 끝까지 읽어들인다. 역시 파일 끝에 도달한 후에는 빈 문자열 ""이 리턴된다.- 쓸데없는 실험
- 재밌는 현상 1: 만약 write 함수를 이용해서
f.write('hi\n')
,f.write('hello\n')
이 두 명령어를 실행했다고 하자. 그리고 파일을 에디터로 열어보면 hi와 hello 딱 두 줄만 있다. - 재밌는 현상 2: 현상 1에
f.write('\n')
이 추가로 실행한다면 세 번째 줄에 공백라인이 하나 더 있다. - 재밌는 현상 3: 에디터에서 바로 위의 예처럼 hi와 hello 딱 두 줄만 적고 저장해서
f.readline()
해보면 hello 뒤에는\n
문자가 없이 나온다. - 재밌는 현상 4: 그런데 만약 현상 3에 추가로 한 줄을 띄워서 공백 라인을 하나 만든다면
hi\n
,hello\n
이 됨은 물론\n
이라는 놈이 하나 또 나온다. \n
의 의미: '보여지는' 관점에서 개행문자의 의미는 에디터에서 개행문자를 기준으로 이전 문자열과 이후 문자열은 줄을 나눠서 보여라!는 의미다. 반대로 '입력하는' 관점에서 개행문자의 의미는 그 다음 줄부터 입력할 준비가 되었다!는 의미다.- 에디터에서 엔터키: 단순히 엔터키를 치기 전까지의 편집하던 줄 끝에 개행문자를 붙이는게 아니다. 엔터키를 친 이후 넘어간 라인의 끝에도 자동으로 개행문자를 붙인다. 즉 에디터에서 엔터키란 이전 라인, 이후라인 모두의 끝에 개행문자를 붙인다는 의미다.
- 결론: 의미없다. 그냥 뭐가 다른지 궁금했을 뿐이다. 하나 정하자면
f.write
을 통해 데이터를 입력할 때 에디터에서 마지막에 한 줄 공백라인을 보이고싶다면 파일 끝에 개행문자를 2개 넣어라.f.write('end of file\n\n'
- 재밌는 현상 1: 만약 write 함수를 이용해서
for line in f: print(line, end="")
- f 파일 객체에서 바로 반복문을 돌릴 수 있다.
readline()
처럼 개행문자까지 읽어들인다. 즉 한 줄씩 line 변수에 문자열로 할당된다. readline()
과 달리 콘솔에 출력하면 개행문자가 보이지 않는다. 보여지는 대신 에디터에서처럼 개행이 적용되어 출력된다. 그래서 개행문자가 연달아 입력되어있다면 공백 라인이 여러줄 출력되기도 한다.- print 함수가 기본적으로 개행을 하기 때문에
end=""
를 적어줘서 중복되지 않게 해야 한다. - 가장 빠르고 효율적인 코드라고 공식문서에 적혀있다.
- f 파일 객체에서 바로 반복문을 돌릴 수 있다.
4.3.3 쓰기 함수
f.write(str_data)
: str_data에 들어있는 값을 파일에다가 쓴다. str_data는 문자열이어야 한다. 숫자거나 boolean이라면 에러난다. 리턴값은 쓰여진 문자열의 문자 개수다."hi\n"
을 입력했다면 3이 리턴된다.- JSON 파일로 저장하기!: 파이썬 데이터를 JSON으로 바꾸는 것을 serializing, JSON to Python Data를 deserializing이라고 한다.
import json
json.dumps(my_obj)
: 괄호 안에 넣은 object를 serializing한 문자열을 리턴한다.1
은'1'
,'abc'
는"'abc'"
,[1, 2, 'abc']
는"[1, 2, 'abc']"
로 바꿔준 값을 리턴하는 것. 결국 이 문자열을 파일 스트림을 쓰기모드로 my_json.json 이란 이름으로 열어서 쓰면 json 파일이 만들어지는 것이다.json.dump(object, FILE)
: s가 없어진 그냥 dump다. 매개변수로 저장할 객체와 쓰기 모드로 열린 파일 스트림 객체를 받는다. 이 코드를 실행하면 객체를 serializing한 문자열을 파일 스트림과 연결된 json 파일에 쓴다. 리턴값은 따로 없다.[1, 2, 3]
을'[1, 2, 3]'
문자열로 바꿔서 파일에 쓰고, 파일을 에디터에서 열어보면[1, 2, 3]
이라고 적혀있다.my_var = json.load(FILE)
: load 함수는 json 파일과 읽기 모드로 연결된 파일 객체를 매개변수로 받는다. 그리고 json 파일을 deserializing해서 데이터 객체로 만든 후 my_var 변수에 할당한다.
- 즉 정리하면 "
쓰기모드 파일객체 + json.dump
"와 "읽기모드 파일객체 + json.load
" 요렇게만 잘 쓰면 끝이다.
4.3.4 기타 관련 함수
with
: 함수가 시작되면 파일이 열리고, 함수가 끝나면 파일이 닫힌다. 파일 객체는 빌트인 메소드로__enter__()
와__exit__()
를 가지고 있다. 여기서 exit 메소드가 실행되면 파일 스트림이 닫히게된다. 이 메소드가 with에서 구현되어있다. 그래서 아래처럼 가능한 것.with open("foo.txt", "w") as f: f.write("Life is too short, you need python")
f.closed
: 파일 객체인 f가 close 되었는지 확인할 수 있는 boolean 값이다. 닫혔으면 True를 리턴한다.sys
: 파일을 python으로 실행할 때 파일 외부에서 매개변수로 데이터를 받아올 수 있게 한다.- 예를 들어 아래 코드가
sys1.py
라는 파일이라면python sys1.py
로 코드를 실행할 것이다. 여기서 python 명령어 다음에 오는 것이 매개변수다. sys.argv
는 이 매개변수들을 여러개 받아서 저장한 리스트다.'python sys1.py aaa bbb ccc'
라고 명령어를 터미널에서 실행하면aaa bbb ccc
가 출력될 것이다.- 아래 코드에선 2번째 원소부터 반복을 돌렸는데 첫 원소부터 돌리면 첫 번째 원소는
"sys1.py"
일 것이다.
# 파일명: sys1.py, 명령어: python sys1.py aaa bbb ccc import sys args = sys.argv[1:] for i in args: print(i) # => aaa # bbb # ccc
- 예를 들어 아래 코드가
5. 클래스
기본 구조는 다음과 같다.
class MyClass(ParentClass):
<클래스 변수 1>
<클래스 변수 2>
...
def 클래스함수1(self[, 인수1, 인수2,,,]):
<수행할 문장 1>
<수행할 문장 2>
...
def 클래스함수2(self[, 인수1, 인수2,,,]):
<수행할 문장1>
<수행할 문장2>
...
...
클래스 내 로컬 함수를 정의할 땐 무조건 매개변수로 self 넣어줘야 한다. 인스턴스를 생성한 후 '인스턴스.함수' 형태로 함수를 실행하면 자동으로 매개변수로 self를 넣어주기 때문이다.
def __init__(self, *args): ~~
: init 함수는 생성자라고도 하며 인스턴스가 만들어질 때 항상 실행된다. self 무조건 들어감.클래스 상속은 뒤에
()
안에 상속받을 클래스를 적어주면 된다.연산자 오버로딩: 객체끼리 +, -, *, / 등의 연산을 할 수 있다.
- 예를 들어 A라는 클래스에
__add__
함수를 추가하면 + 연산이 가능하다. - A로 만든 a 객체가 앞에 있든 뒤에 있든 + 연산은 수행 가능하지만, self의 적용은 달라진다.
a + b
인 경우self
는a
이고,b + a
인 경우에self
는b
이다. 두 객체 중 하나에만 add가 있으면 된다.
- 예를 들어 A라는 클래스에
변수 종류
- global variable: 말 그대로 전역변수. 어느 위치에서도 호출 가능
- member variable: init 함수 밖에서 선언된 변수. 결국 클래스 변수다.
클래스명.변수명
형태로 접근할 수 있다. 클래스에서도 호출할 수 있지만 인스턴스 변수 각각에서도 이 변수를 가지고 있어서 호출 가능하다. 즉 Hello 클래스에서 a, b 인스턴스를 만들었을 때 셋 모두 member variable을 갖고 있어서 다른 값을 설정할 수 있다. 웬만하면 사용하지말고 꼭 필요한 경우, 예를 들어 인스턴스 개수를 설정할 때 클래스의 멤버 변수만 활용하라고 말하는 사람들이 있다. 인스턴스에서는 웬만하면 호출하지 않는걸로. - instance variable: init 함수 안에서 선언된 변수. 만약 여기서 선언되지도 않고 대입되지 않았더라도
인스턴스.새로운인스턴스변수 = 값
형태로 적어주면 인스턴스에 변수가 추가된다. - 인스턴스 Namespace --> 클래스 Namespace --> Global Namespace 순서로 scope를 올려가며 변수를 찾는다.
- 인스턴스 객체에서 클래스 멤버 변수로 접근하려면
myClass.__class__.classMember = 10
처럼__class__
메소드를 활용한다.
클래스의 함수를 method라고 한다. 일반 함수를 function
init
함수가 아니더라도 다른 함수에서 인스턴스 변수를 선언할 수 있다.init
함수가 실행되기 전엔 변수가 존재하지 않는다. 호출해도 없는 속성이라고 에러난다. AttributeError.클래스를 만들거면 웬만하면
object
클래스를 상속하자.클래스의 객체를 print했을 때 원하는 출력물을 지정하고 싶으면
__repr__
메소드를 만들고 원하는 문자열을 return 하면 된다. 매개변수는 오직 self만.def __repr__(self): return "(%d, %d, %d)" % (self.x, self.y, self.z)
super: 아래 코드가 예시다. 부모 클래스의 메소드를 그대로 자식 클래스에서 쓰고 싶을 때 super를 쓴다.
super(내클래스, self).메소드명(매개변수)
형태로 쓴다.class Employee(object): def __init__(self, employee_name): self.employee_name = employee_name def calculate_wage(self, hours): self.hours = hours return hours * 20.00 class PartTimeEmployee(Employee): def calculate_wage(self, hours): self.hours = hours return hours * 12.00 def full_time_wage(self, hours): return super(PartTimeEmployee, self).calculate_wage(hours) milton = PartTimeEmployee('Milton') print milton.full_time_wage(10)
정적 메소드
- 인스턴스를 통하지 않고 클래스를 통해 바로 메소드를 호출하기 위해 정적 메소드를 사용하게 된다. Python에서는 클래스의 정적 메소드를 구현하기 위해 다음과 같이 해당 메소드가 정적메소드임을 등록해야 한다.
Method Name = staticmethod(Method in Class)
- 외부에서 호출 시에는 위의 Method Name으로 호출 하게 된다.
Private 멤버
- Python에서는 문법적으로 클래스의 private 멤버를 지원하지 않는다. 대신 Name mangling을 이용하여 이와 유사한 기능을 수행하도록 할 수 있다.
- 멤버 변수나 함수가
__
로 시작하는 경우 외부에서 참조할 때는 자동으로_클래스이름__멤버이름
으로 변경하게 된다. 이로써 원래의 멤버이름으로는 접근 시 에러가 발생하게 되어 private 멤버 처럼 사용할 수 있게 된다. 당연히 클래스 내부에서 사용 시에는 멤버 변수 이름 그대로 사용 가능하다.
class MyClass(parent): """ Class Document """ __privateMember = 0 def __init__(self): pass
6. 모듈
- 함수 혹은 변수들로 이루어진
.py
확장자의 텍스트 파일이다. abc.py
라는 모듈 파일이 있다면 이 파일이 위치한 디렉토리에서 python 실행 후import abc
하면 된다. 이렇게 모듈 파일 이름으로 단순하게 import하는것을 generic import라고 한다.import abc
에서 import는 abc를 쓸 수 있게 해준다는 의미다. import 없이는 abc 라고 입력했을 때 선언되지 않은 변수라고 에러가 뜬다. 저 명령어를 쳐 줘야 abc가 의미를 갖는다.- abc 모듈에 AAA라는 함수가 있다고 할 때,
import abc
했다고 그냥 바로AAA
함수를 쓸 순 없다.abc.AAA
라고 해야 한다. 앞에 abc를 생략하고 싶다면from abc import AAA
라고 하면 바로 AAA 쓸 수 있다. 함수라면 뒤에 () 생략한다. 함수 이름만 써준다. - Universal Imports:
from math import *
이렇게 하면된다. 썩 좋은 방법은 아님. 왜냐면 기본적으로 이미 import돼있는 수많은 변수나 함수가 존재한다. 근데 저렇게 math의 모든 것을 import 해버리면, 뭔가가 겹칠 수 있다. 같은 이름의 변수나 같은 이름의 함수들이. 좋은 방법이 아니다. - 만약 모듈에 함수나 변수만 덩그러니 있는게 아니라 실제 실행되는 명령어가 있다고 치자. 예를 들어 print문이 있다고 하면 import abc를 했을 때 그 코드들이 실행이 되게된다. import했을 때는 실행이 안되도록 하려면
if __name__ == "__main__":
이 if 블락 안에 실행문들을 넣으면 된다. 실제 python 명령어로 실행됐을 때만 실행 코드들이 동작하도록 만드는 조건이다. - 다른 모듈 사용할 때 import는 클래스 밖에서 사용한다.
- vector.py 모듈과 모듈 내의 Vector class를 직접 만들었다고 하자.
- 이 Vector 클래스는
norm
이라는 메소드를 갖는데 이 메소드가math
모듈의sqrt
메소드를 사용한다. - 이럴 경우
import math
를 클래스 내부에서 선언하면 norm 메소드가 동작하지 않는다. 클래서 definition 바깥에서 import 해줘야 한다.
- 파이썬 모듈 저장 디렉토리 추가하기
- 터미널에서 파이썬 repl을 실행한 후
import sys
한다. 그리고sys.path
를 입력해보면 리스트 형태로 경로들이 존재한다. 여기에 리스트이므로 append 함수로 경로를 문자열로 추가해주면 그 경로에 위치한 모듈은 바로 import해서 쓸 수 있다. - 혹은 터미널에서
set PYTHONPATH = C:\Python\Mymodules
형태로 지정해줄 수도 있다.
- 터미널에서 파이썬 repl을 실행한 후
7. 2진수
0b
를 앞에 붙여주면 된다.2진수를 print 하면 10진수 형태로 출력된다.
bin(integers)
: 정수를 매개변수로 받아서 문자열 형태인 2진수를 리턴한다.oct(int)
,hex(int)
: 8진수, 16진수로 바꾸는.int(str_num, 자리수)
: 첫 번째 매개변수는 문자열로 이루어진 숫자, 두 번째는 진법을 나타내는 숫자다.- 10이 디폴트값이고 2, 8, 16 등이 올 수 있다.
- 진법 수는 2 이상 36 이하다.
- 첫 번째 매개변수에 2, 8, 16진수를 나타내는 0b, 0o, 0x가 붙은 문자열이 들어올 수도 있다. 이 때는 이 진법에 맞춘 숫자가 두 번째 매개변수에 들어가야된다. 다른게 들어가면 에러난다.
shift 연산: operator 모듈의
lshift
,rshift
다.<<
와>>
가 매칭된다.lshift
,<<
가 2배씩 커지는거고,rshift
,>>
가 2배씩 작아지는 거다.- 하지만 항상 2배씩 변하는 것은 아니다. 예를 들어
0b0010 >> 2
하면0
이 되어버린다. - 오른쪽으로 1이 한 칸씩 가지만 끝에 도달하면 아예 사라지기 때문이다. 이 때문에 숫자 변화가 항상 1/2이 되는 것은 아니다.
bitmask
: 예를 들어 오른쪽에서 3번째 자리수가 1인지 확인하고 싶다면0b100
과 검사하고싶은 수를&
연산하면 된다. 결과가 0보다 크면 1인거고, 아니면 0인거다.원하는 비트 1로 만들기: 원하는 비트만 1인 수를 만들고
|
연산한다. 즉 오른쪽에서 세 번째 비트를 on하고 싶다. 그러면0b100
과 그 수를|
연산하고 결과값을 쓰면 된다.비트를 다 뒤집고 싶다면: 원하는 수의 2진법 표현과 똑같은 자리수만큼 1로 채워서
^
연산하면 된다.0b110101
을 뒤집고싶으면 똑같은 자리수로0b111111
을^
한다.def flip_bit(number, n): return bin(number ^ (0b1 << n-1))
8. 자주 쓸 것 같은 함수들
isalpha()
: 문자열이 오로지 알파벳으로만 이루어져있는지isdigit()
: 문자열이 오로지 숫자로만 이루어져있는지dir(math)
: math 모듈에서 사용 가능한 모든 것을 리스트로 보여준다.abs(-5), max(1,2,3), min(-4, -2, -10)
: 절대값, 최대값, 최소값. 저렇게 단순한 콤마로 구분해서 여러 수를 넣을 수 있는 것은 콤마만 적으면 자동으로 튜플이 되기 때문이다.type(something)
: something의 타입을 리턴함.import random
randint(low, high)
많이 쓰인다. low부터 high까지 임의의 정수 하나를 리턴한다. 중요한건 high 포함이고 둘 모두 정수여야 한다.random.choice(iterable)
: iterable에서 무작위로 원소 하나 리턴한다.random.shuffle(iterable)
: iterable을 무작위로 섞는다.
re
모듈에서sub
함수가 있다.re.sub(pattern, replacement, string)
으로 쓰면 된다. 매개변수가 2개 더 있지만 저렇게만 자주 쓰일듯.my_str.lower()
,my_str.upper()
는 호출되는 대상을 바꾸지 않는다. 다시 대입해줘야.filter(function, iterable)
: iterable의 원소를 하나하나 빼내서 function에 적용한 후 리턴값이 True이면 리스트에 집어넣는다. 그리고 최종적으로 리스트를 리턴한다. Python2에선 리스트, Python3에선 필터 객체다.map(func, iterable)
: filter와 다르게 iterable의 원소 하나하나를 func에 대입해서 나온 결과값을 리턴 객체에 넣는다. 2에선 리스트, 3에선 맵 객체locals()
: 함수 내에서 실행하면 함수의 로컬 변수들을 딕셔너리 형태로 리턴한다.all(iterable)
: iterable 원소들이 모두 참인 경우 True 리턴한다.any(iterable)
: 참인 원소가 하나라도 있으면 Truechr(아스키코드값)
: 아스키코드값을 받아서 문자로 리턴한다.ord
는 그 반대다.divmod(7, 3)
: 7을 3으로 나눈 몫과 나머지를 튜플로 리턴한다.eval('1+2')
: 실행 가능한 함수나 수식 등을 문자열로 받아서 결과값을 리턴한다. 이 코드는 3을 리턴한다.eval('divmod(7,3)')
->(2, 1)
repr(object)
: 객체를 출력 가능한 문자열로 변환해서 리턴한다. 예를들어repr('hi'.upper())
->"'HI'"
lambda
: 이름 없는 함수이며 주로 간단한 함수식을 표현할 때 쓴다.lambda 인수1, 인수2, ... : 인수를 이용한 표현식
으로 나타낸다. 인수를 이용한 표현식 부분이 자동으로 리턴된다.id(object)
: 주소값 리턴sorted
,zip
,type도
기억.import os
os.environ
: 시스템 환경변수값을 딕셔너리 객체로 리턴os.chdir
: 디렉토리 변경os.getcwd
: 현재 디렉토리 문자열 리턴os.system("명령어")
: 터미널에서 명령어 실행한 결과값 리턴os.mkdir(디렉토리명)
: 디렉토리를 생성한다.os.rmdir(디렉토리)
: 비어있는 디렉토리 삭제os.unlink(파일)
: 파일 삭제os.rename(src, dst)
: src 파일을 dst로 이름 변경
import webbrowser
: 브라우저에서 URL을 연다.webbrowser.open("URL")
webbrowser.open_new("URL")
import shutil
->shutil.copy("src.txt", "dst.txt")
파일 카피다. 만약 목표 디렉토리에 같은 이름의 파일이 있다면 덮어쓴다.import glob
->glob.glob("/users/gyubin/dev/Q*")
지정 디렉토리의 파일명을 리스트화한다. Q*는 q로 시작하는 파일들만으로 한정한 것.import tempfile
임시파일 관련 모듈이다.
9. 예외처리
9.1 에러 처리 기본
try:
f.open('wow.txt', 'r')
except [발생에러[as 에러메시지변수]]: # []는 생략해도 된다는 의미
pass # 에러 나든 말든 넘기고 싶으면 pass
else:
pass
finally:
f.close()
- 에러가 날 수 있는 코드를 try에 넣고, 에러가 났을 때 처리를 except에 넣는다. 에러가 발생하지 않았을 경우 실행되는 코드는 else안에 둔다. finally는 에러가 나든 안나든 무조건 실행해주는 코드로 주로 파일 스트림 객체를 닫는데 쓰인다.
- []는 생략해도 된다는 의미다. 그냥 except만 적어도 되고, 에러를 명시해줘도 되고, 그 에러를 내 입맛에 맞게 바꿔불러도 된다.
try:
4 / 0
except ZeroDivisionError as e:
print(e)
# => 출력: division by zero
9.2 에러 일으키기 raise
다음은 Bird 클래스를 상속하는 자식 클래스는 무조건 fly 메소드를 오버라이드 해야한다는 의미의 코드다.
class Bird:
def fly(self):
raise NotImplementedError
class Eagle(Bird):
pass
eagle = Eagle()
eagle.fly()
class Eagle(Bird):
def fly(self):
print("very fast")
eagle = Eagle()
eagle.fly()
10. 패키지
10.1 기본
복잡한 혹은 큰 규모의 파이썬 프로그램이라면 패키지를 만들어서 관리하는게 유용하다. 예를 들어 다음과 같은 구조가 있다. 아래 패키지에서 echo.py 모듈을 사용하려면
game/
__init__.py
sound/
__init__.py
echo.py
wav.py
graphic/
__init__.py
screen.py
render.py
play/
__init__.py
run.py
test.py
- (O)
import game.sound.echo
->game.sound.echo.echo_test()
- (O)
from game.sound import echo
->echo.echo_test()
- (O)
from game.sound.echo import echo_test
->echo_test()
- (-)
import game
-> 디렉토리를 import하면 game 디렉토리의__init__.py
의 내용만 참조 가능 - (X)
import game.sound.echo.echo_test
이건 에러난다. 이렇게.
으로 구분해서 디렉토리의 모듈을 import할 땐 마지막에 무조건 패키지나 모듈이 되어야 한다. 저렇게 함수가 들어가면 안된다.
하지만 디렉토리 자체를 import할 순 없다. 예를 들어 import game
한 후에 from game.sound.echo import echo_test
사용은 불가하다. 이렇게 디렉토리를 import 하는 경우는 __init__.py
의 내용만 가져온다.
__init__.py
에 대하여
10.2 해당 디렉토리가 패키지의 일부라는 것을 나타내주는 것이다. 이거 없이 패키지를 import하면 에러난다. 파이썬3에선 없어도 되는걸로 바뀌었지만 그래도 하위호환성을 위해 해주는게 좋다. 이 안에 all같은 필요한 몇가지 요소들을 적어준다.
__all__
10.3 from game.sound import *
이렇게 코드를 짜면 sound 패키지의 모든 모듈을 import한다는 의미다. 이 때 __init__.py
에 __all__
이 있어야 정상적으로 작동한다. __all__ = ['echo']
이렇게 리스트 안에 모듈명을 문자열로 집어넣어주면 된다.
물론 from에서 마지막이 패키지로 끝나는 경우에 위의 작업이 필요한것이지 만약 from에서 마지막이 모듈로 끝난다면 그냥 import * 해도 속한 모든 메소드들이 호출 가능해진다. 하지만 이는 좋은 방법이 아니다.
'파이썬' 카테고리의 다른 글
파이참(pycharm) 단축키 정리 (0) | 2021.09.15 |
---|---|
정규표현식(Regular Expression) (0) | 2018.04.09 |
Jupyter Notebook이란? (0) | 2018.04.03 |
iterator, generator 사용법 (0) | 2018.04.03 |
decorator(wrapper) 사용법 (0) | 2018.04.03 |