Python입문
개인 공부용 요약노트. 상세한 설명은 없고, 키워드, 코드위주로 작성
print('나는\n고경수') # 한줄띄우기
print('나는\t고경수') # 탭
print('\\') # 이스케이프
print('나는\\n고경수')
print('나는\'고경수\'')
print("나는'고경수'")
S = 'xxxxSPAMxxxxSPAMxxxx'
S.replace('SPAM','EGGS')
S.replace('SPAM','EGGS',1)
S = 'xxxxSPAMxxxxSPAMxxxx'
where=S.find('SPAM')
S[where]
'-'.join(['a','b','c'])
S='spammy'
S[3:5]='xx'
mm을 xx로 바꾸고 싶은데 문자열은 불변리스트라서 바꿀 수 없다.
전략: 문자열을 잠시 가변객체인 리스트로 바꾼뒤 리스트에서 자유롭게 편집하고 그 다음에 다시 문자열로 만들자.
L=list(S)
L
L[3:5]
L[3:5]=['x','x']
L
S=''.join(L)
S
s='bob,hacker,40'
s.split(',')
'addr: %s to %s' % ('seoul','jeonju')
잘못된 사용예시1 (리스트는 안됨)
'addr: %s to %s' % ['seoul','jeonju']
잘못된 사용예시2 (묶지않아도 안됨)
'addr: %s to %s' % 'seoul','jeonju'
% 연산자
는 왼쪽에 문자열 오브젝트, 그리고 오른쪽에는 명시적인 튜플이 있어야 연산이 진행된다.
연산자라는 포인트를 이해하면 아래와 같은 문법도 가능함을 알 수 있다.
s = 'addr: %s to %s'
s % ('seoul','jeonju')
'이름:{},나이:{},성별:{}'.format('고경수','24','남')
s = '고경수'
n = 25
print(f'이름={s}, 나이={n}')
파이썬 3.6부터 사용할 수 있는 기능.
- 문자열 맨 앞에(따옴표앞) f를 붙인다.
- 사용하고 싶은 변수, 값을 중괄호 안에 넣는다.
- 출력한다.
x=[2**i for i in [0,1,2,3,4,5]]
x
[i+j for i in ['stat','math'] for j in '12345']
[i+j for i in 'XY' for j in '123']
a=[[11,12,13],
[21,22,23],
[31,32,33]]
a
a[0][0]
a[0][1]
0 | 1 | 2 | |
---|---|---|---|
0 | 11 | 12 | 13 |
1 | 21 | 22 | 23 |
2 | 31 | 32 | 33 |
-
2차원 배열의 느낌!!!
-
1차원 배열을 사실상 다차원배열로 확장할 수 있는 아이디어를 제공
- 리스트와 비슷하다.
- 차이점1: [ ] 대신에 ( )를 사용한다.
- 차이점2: 불변형이다. (값을 바꿀 수 없음)
- 차이점3: 하나의 원소로 이루어진 튜플을 만들때는 쉼표를 붙여야 함.
a=(1,)
a
a + (2,)
- 차이점4: (의미가 명확할때) 튜플의 괄호는 생략가능하다.
a=1,2
a
의미가 명확할때 생략해야함
1,2 + 3,4,5
name,age,sex,height,weight = 'Tom',20,'M',180,70
name
weight
[예제3]: 임시변수 사용없이 두 변수의 값을 교환
a=10
b=20
a,b=b,a
a
b
[예제4]: 함수의 입력으로 튜플을 넣을때
def cal(a,b):
print(str(a) + '+' + str(b) + '=' + str(a+b))
print(str(a) + '-' + str(b) + '=' + str(a-b))
print(str(a) + '*' + str(b) + '=' + str(a*b))
print(str(a) + '/' + str(b) + '=' + str(a/b))
input=[3,4]
cal(input) # 리스트로는 불가능하다.
cal(input[0],input[1])
input=(3,4)
input
cal(*input) # 튜플 언패킹으로는 가능하다.
- 함수를 호출할때 인수앞에 *를 붙여 튜플을 언패킹할 수 있다.
[예제6]: 플레이스홀더
idlist=[('guebin', '202112345','M','Korea'),
('iu', '202154321','F','Korea'),
('hodong', '201812321','M','Korea')]
for name,studentid,sex,nat in idlist:
print(name)
for name , _ , _ , _ in idlist:
print(name)
A={'a','b','c','d'}
B={'c','d','e','f'}
A.union(B)
A|B
A.intersection(B)
A & B
A.difference(B)
A-B
a=set('hello')
a
for i in a:
print(i)
순서가 좀 이상하다 $\to$ 집합은 원래 순서가 없다. $\to$ 인덱싱이 불가능하다. $\to$ 슬라이싱도 불가능
- 집합 컴프리헨션
C={2**x for x in [1,2,3,4]}
C
mydict={'a':[1,2,3],'b':[3,4,5]}
mydict['a']
mydict['a']+mydict['b']
mydict[0] # 인덱싱 불가능
- 딕셔너리 컴프리핸션
X={x:x**2 for x in [1,2,3,4]}
X
욕심
: (1,2,3)+(2,3,4)=(3,5,7)
를 계산하고 싶다.
import numpy as np
a=np.array((1,2,3))
b=np.array([2,3,4])
a+b
list
- tuple
- np.array
사이에는 호환성이 좋음
list(np.array(tuple(a)))
예를들어 아래와 같은 문제가 있다고 하자.
$\begin{cases} w+2x+3y+4z=1 \\ 2w+2x+y=9 \\ x-y=4 \\ 3w+x-y+3y=7 \end{cases}$
매트릭스 형태로 위의 식을 표현하면 아래와 같다.
$\begin{bmatrix} 1 & 2 & 3 & 4 \\ 2 & 2 & 1 & 0 \\ 0 & 1 &-1 & 0 \\ 3 & 1 &-1 & 3 \end{bmatrix} \begin{bmatrix} w \\ x \\ y \\z \end{bmatrix}=\begin{bmatrix} 1 \\ 9 \\ 4 \\7 \end{bmatrix}$
양변에 $\begin{bmatrix} 1 & 2 & 3 & 4 \\ 2 & 2 & 1 & 0 \\ 0 & 1 &-1 & 0 \\ 3 & 1 &-1 & 3 \end{bmatrix}$의 역행렬을 취하면
$\begin{bmatrix} w \\ x \\ y \\z \end{bmatrix}=\begin{bmatrix} 1 & 2 & 3 & 4 \\ 2 & 2 & 1 & 0 \\ 0 & 1 &-1 & 0 \\ 3 & 1 &-1 & 3 \end{bmatrix}^{-1}\begin{bmatrix} 1 \\ 9 \\ 4 \\7 \end{bmatrix}$
from numpy.linalg import inv
A=[[1,2,3,4],[2,2,1,0],[0,1,-1,0],[3,1,-1,3]]
b=[1,9,4,7]
Aarr=np.array(A)
barr=np.array(b)
inv(Aarr) @ barr
- 인덱싱 (슬라이싱 포함)
A=np.array([[11,12,13,14,15],[21,22,23,24,25],[31,32,33,34,35]])
A
[예제1] (3,1)에 접근하여 보자!
A[2][0]
A[2,0] # list와의 차이점
[예제4] 1행중에서 1,3,5열에 접근해보자.
A[0,[0,2,4]] #방법 1
A[0][[0,2,4]] #방법 2
b=(0,2,4)
A[0,b]
- 기본인덱싱: 인덱스, 슬라이싱을 활용
- 예1:
A[1,1]
- 예2:
A[1,0:2]
- 예1:
- 팬시인덱싱(응용인덱싱): 인덱스를 정수배열로 전달,
np.ix_
함수를 활용한 인덱싱, 부울값 인덱싱- 예1:
A[0,[0,2,4]]
, 정수배열 인덱싱 - 예2:
A[np.ix_(a,b)]
, np.ix함수를 활용한 인덱싱 - 예3:
c[c>0]
, 부울값인덱싱
- 예1:
-
numpy
를 배우는 방법
인터넷+자동완성+contextual help
dict
와 호환성이 좋은 새로운 자료형이 있는데, 그것이 바로 pandas
이다.
근본적인 차이: list
는 번호로, dict
는 keyword로 접근한다.
- 인덱싱, 슬라이싱 vs 맵핑 note: 리스트는 키워드로 정보검색이 불가능하다. note: 딕셔너리는 인덱스로 정보검색이 불가능하다.
d={'새로이':[30,600,4.0],
"이서":[20,950,4.2],
"일권":[28,950,2.3],
"현이":[28,650,3.8]}
import pandas as pd
pd.DataFrame(d) ## 판다스자료형 = 데이터프레임을 선언하는 방법
df=pd.DataFrame(d).T
df
note: 이서의 정보를 알고 싶다면? (딕셔너리 느낌)
df.loc['이서']
note: 칼럼이름을 정하고 싶다면?
df.columns=['age','toeic','gpa']
df
df.loc[:,'gpa']
note: 2-3번째 칼럼을 불러오자! (넘파이느낌)
df.iloc[:,1:3]
note: 토익점수를 불러오고 싶다면?
df.loc[:,'toeic']
note: age~toeic까지의 정보를 얻고 싶다면?
df.loc[:,'age':'toeic']
note: 새로이~일권까지의 정보를 얻고 싶다면?
df.loc['새로이':'일권',:]
note: 토익점수가 800보다 높은사람을 부르고 싶다면?
df.query('toeic>800')
note: 나이가 23보다 많고 토익점수가 800보다 높은 사람을 부르고 싶다면?
df.query('age>23 & toeic>800')
- 많은 교재에서 정의를 회피함
- 비유적 설명 , 다른 대상을 가져와서 설명
- 클래스는 과자틀과 비슷하다. 클래스란 똑같은 무엇인가를 계속 만들어 낼 수도 있는 설계도면이고 객체란 클래스로 만든 피조물을 뜻한다. (점프투파이썬)
- In object-oriented programming, a class is an extensible program-code-template for creating objects, providing initial values for state (member variables) and implementations of behavior (member functions or methods).`
- 직접적 설명
- 복제를 위한 확장가능한 프로그램 코드의 유닛
좀더 정리하여 말하면,
(1) 개념의 인지
(2) 복사하고 싶은 속성을 추림
(3) 복사가능한 어떤 틀을 만듬 (=클래스를 정의)
(4) 틀에서 인스턴스를 만든다 (=클래스에서 인스턴스를 만든다)
class MooYaHo(): ### MooYaHo라는 이름을 가진 클래스 선언
title="농심 무파마" ### 클래스안에서 정의된 변수1
img=Image.open('mooyaho1.jpg').resize((200,200)) ### 클래스안에서 정의된 변수2
don="그만큼 맛있으시단거지" ### 클래스안에서 정의된 변수3
def memeshow(self): ### 클래스안에서 정의된 함수*
print(self.title)
display(self.img)
print(self.don)
규칙1: 클래스내에서 함수를 선언하면 반드시 첫번째 인자는 self
를 넣어야 한다. --> self
가 뭘까?
규칙2: 클래스 내에서 정의한 변수 (예를들면 title
, img
, don
)를 사용하려면
-
self.title
,self.img
,self.don
-
MooYaHo.title
,MooYaHo.img
,MooYaHo.don
클래스에서 인스턴스를 찍어내는 방법
- 함수사용법과 비슷
- 클래스 이름을 쓰고 콘텐츠를 구체화시키는 과정에서 필요한 입력1, 입력2를 ()에 넣는다.
- MooYaHo의 경우는 따로 입력이 없으므로, 그냥 MooYaHo하고 입력을 비워둔다. 즉
MooYaHo()
로 생성
성능1: 인스턴스에서 .
을 찍고 접근할 수 있는 여러 자료들을 정의할 수 있다.
성능2:인스턴스에서 .
을 찍고 쓸 수 있는 자체적인 함수(=method라고 함)를 정의할 수 있다.
- 출력만 살짝 바꾸어서 MooYaHo2를 만들고 싶다.
--> MooYaHo의 모든 내용은 그대로 가져오고, 그 살짝만 다시 조정하면 된다.
#### 이런식으로 할 필요 없다.
class MooYaHo2(): ### MooYaHo라는 이름을 가진 클래스 선언
title="농심 무파마" ### 클래스안에서 정의된 변수1
img=Image.open('mooyaho1.jpg').resize((200,200)) ### 클래스안에서 정의된 변수2
don="그만큼 맛있으시단거지" ### 클래스안에서 정의된 변수3
def memeshow(self): ### 클래스안에서 정의된 함수*
print('☆☆☆☆☆☆['+self.title+']☆☆☆☆☆☆')
display(self.img)
print('형돈:'+self.don)
class MooYaHo2(MooYaHo):
choi='무야~~~~~호~~~!!!'
def memeshow(self): ### 클래스안에서 정의된 함수*
print('☆☆☆☆☆☆['+self.title+']☆☆☆☆☆☆')
display(self.img)
print(self.choi)
print('형돈:'+self.don)
__str__
__repr__
__init__
-
상속
-
객체임베딩(객체 내장)
- 전역 변수 > 클래스 변수 > 메소드 변수 > 인스턴스 변수
-
연산자 오버로드 핵심아이디어
- 클래스가 일반 파이썬 연산을 재정의하는 것
- 여기에서 연산은 단순히 더하기 빼기를 의미하는게 아니라,
print()
,+
,[0]
와 같은 파이썬 내장문법을 모두 포괄하는 개념이라 이해하는 것이 옳다.
a=11
if a<5:
print('a=....1,2,3,4')
elif a>10:
print('a=11,12,13,....')
else:
print('a=5,6,7,...,10')
a=2
if a==1:
print('a=1')
if만 있어도 작동한다.
for i in [1,2,3,4]:
print(i)
for i in (1,2,3,4):
print(i)
for i in '1234':
print(i)
1
2
3
4
-
의문
for i in ???:
print(i)
에서 물음표 자리에 올 수 있는 것이 무엇일까?
??? 자리에 올 수 있는 것은 dir()하여 __iter__()
라는 메서드가 있는 object이다.
a=1
dir(a)
['__abs__',
'__add__'
.
.
.
.
.
.
`to_bytes']
int클래스의 인스턴스는 __iter__()
가 없다!
-
list, pd.DataFrame, np.array 는 모두 __iter__()
함수가 있다. 따라서 iterable한 오브젝트이다.
iterable한 오브젝트는 iterator로 만들 수 있는 특징이 있다.
iterable한 오브젝트를 어떻게 iterator로 만드는가?
L=[[1,2,3],[3,4,5]]
import pandas as pd
df=pd.DataFrame(L)
dfiter1=df.__iter__()
dfiter2=iter(df)
dfiter1?
-
dfiter1은 generator라는 클래스에서 만들어진 인스턴스 오브젝트이다.
dir(dfiter1)
dfiter1.__next__()
–
for 문의 작동원리
for i in L:
print(i)
(1) iter함수를 사용해서 L을 iterator로 만든다.
(2) iterator에서 .__next__()
함수를 호출하고 결과를 i에 저장한뒤에 for문 블락안에 있는 내용(들여쓰기 된 내용)을 실행한다.
(3) StopIteration 에러가 발생하면 for 문을 멈춘다.
Liter=iter(L)
Liter.__next__()
Liter.__next__()
Liter.__next__()
-
for문의 정석은 아래와 같이 range()를 사용하는 것이다.
for i in range(5):
print(i)
-
range(5)
의 정체는 그냥 iterable object이다.
-
그래서 언제든지 iterator로 바꿀 수 있다.
a = range(5)
aiter=iter(a)
aiter.__next__()
aiter.__next__()
. . .
aiter.__next__()
-
???? 자리에 iterator 자체가와도 무방할것 같다.
-
확인
L=iter([1,2,3,4])
for i in L:
print(i)
f=open('test.txt')
a=f.read()
print(a)
hello
hello2
hello3
f.closed
false
f.close()
f.closed
True
f가 닫힌 상태에서는 더 이상 읽을 수가 없다.
파일을 닫지 않는다고 해서 큰 문제는 없어보이지만 그냥 닫는것이 좋다.
- motivation
-
생각해 보니까 파일을 열면 항상 닫아야 한다.
이처럼 쌍(시작-끝)으로 수행되는 처리가 반복적으로 발생하는 경우가 있는데 그때마다 .close()
메소드 따위를 쓰는 것이 번거롭게 느껴진다.
예를들면 파일을 열었으면 적당한 동작뒤에 알아서 닫아졌으면 좋겠다는 것이다.
이러한 모티브에서 구현된 것이 with문 이다.
with open('test.txt') as g:
print(g.read())
hello
hello2
hello3
g.closed
True
잘 닫아졌다.
-
기본사용법
with의 사용법은 직관적으로 이해가 가능하지만 그래도 다시한번 살펴보자.
with blabla as variable:
yadiyadi
yadiyadi2
(1) with blabla as variable
에서 blabla가 실행된다.
(2) blabla의 실행결과로 어떠한 특별한
오브젝트가 만들어지는데 그 오브젝트를 우리가 variable로 부르기로 한다.
(3) 탭으로 들여쓰기된 부분, 즉 yadiyadi, yadiyadi2 가 순서대로 실행된다.
(4) 탭으로 들여쓰기된 부분이 실행되고 난 뒤에 g.closed()
따위의 미리 약속된 어떠한 코드가 실행되는것 같다.
-
동작원리
비밀은 __enter__
와 __exit__
메소드에 있다.
(for문 복습) for i in ...:
에서 ...
에 올 수 있는 오브젝트는 __iter__
메소드가 정의되어 있어야 한다. 이러한 오브젝트를 iterable한 오브젝트라고 한다.
(with문) with ... as variable:
에서 ...
의 실행결과로 생성되는 오브젝트는 __enter__
와 __exit__
메소드가 정의되어 있어야 한다.
- 이중
__enter__
는 with문이 시작되면 자동으로 실행된다. - 이중
__exit__
는 with문이 끝나면 자동으로 실행된다.
-
예제
class MooYaHo:
def __init__(self):
print('init')
def __enter__(self):
print('무야호')
def __exit__(self,exc_type,exc_value,traceback): # self 이외의 3가지 변수는 예외처리에 관련된 변수인데 여기서는 다루지 않음.
print('그만큼 신나시는거지')
with MooYaHo() as a:
print('.')
- 함수도 객체다
def myadd(a,b):
return a+b
myadd(1,2)
?myadd
-
Type이 function이다?
-
myadd 는 function class의 instance이다.
-
결국 myadd 역시 하나의 오브젝트에 불과하다.
myadd(1,2)
myadd의 입력 1,2는 int class의 인스턴스 오브젝트였음.
즉 문법의 논리로 보면 함수의 입력에 들어갈 수 있는것은 오브젝트이면 된다.
그런데 함수 자체도 오브젝트이다 $\to$ 함수도 함수의 입력으로 쓸 수 있다?
-
예제1
def calc(fun,a,b):
return fun(a,b)
calc(myadd,-3,3)
이처럼 함수자체를 입력으로 받거나 출력으로 보내는 함수를 higher-order function이라고 한다.