자료형 중 `숫자`는 크게 `4가지`가 있다. 1. Integer 2. Float 3. Boolean 4. Complex
Integer는 정수형으로 숫자의 범위가 없다. 따라서 오버플로우가 없다. 그리고 python에서 정수의 종류는 한 가지
Float는 부동소수로 숫자의 범위가 있다. 따라서 오버플로우가 있다. ※ 0.1 + 0.1 + 0.1 의 결과값은 0.3000000000000004로 나온다. Why? --> 컴퓨터는 근사값을 계산하기 때문에 정확한 값을 출력하지 못한다.
※ a = 2e3 --> 2000.0 b = 2e-3 --> 0.002
그리고 컴퓨터가 정수와 부동소수의 저장 방식의 차이 때문에 .의 유무로 정수인지 부동소수인지 판단한다.
Boolean은 True / False True는 숫자 1에 대응되고 False는 숫자 0에 대응된다. ※ True 처럼 bold채로 쓰인 것은 키워드이다.
Complex는 복소수로 j로 표시한다. ex) i = 1 + 3j : (1+3j)
`문자`는 크게 `3가지`가 있다. 1. String 2. Bytes 3. Bytearray
String은 python3 버전에서 unicode문자에 해당한다. Byte는 문자 앞에 b를 붙이면 byte문자로 인식하고 ASCII코드에 해당한다. ex) a = b'안녕' SyntaxError: bytes can only contain ASCII literal characters
Python Tip1 Python에서는 변수를 식별자라고 명칭한다. 이때 식별자는 생성 규칙이 정해져 있다.
변수 명명규칙
1 2 3
1. 영문으로 써야한다. 2. 첫번째문자는 특수문자를 사용할 수 없다. 3. 미리 정의되어있는 문자는 사용할 수 없다.
Python Tip2 파이썬은 동적타입, 즉 타입을 지정해주지 않아도 자동으로 지정해주기 때문에 정수형인지 부동소수점인지 문자인지 등을 명시하지 않아도 타입이 지정된다.
Variable Type Data/Info ------------------------------- a int 1 abc bytes b'abc' b int 2 c int 3 f bool False i complex (1+3j) keyword module <module 'keyword'from'C<...>conda3\\lib\\keyword.py'> t bool True w str ㅇㅇ
문자열 연산 및 예외 연산
1 2 3 4 5 6 7 8 9 10 11
'정지혁' * 3 : 정지혁정지혁정지혁
'정' + '정' : '정정'
'정' + 1 : TypeError: can only concatenate str (not"int") to str
# 데이터 타입에 따라서 지원되는 연산이 다르다.
Markdown 문법
아주 기본적인 마크다운 문법을 배웠고 jupyter에서 작동하는 커멘드를 배웠다.
ESC : 명령 커멘드
H: Help (도움말)
ESC + Y: Code mode
ESC + M: Markdown mode
ESC + A 현재 라인 위에 새로 추가하기
ESC + B 현재 라인 밑에 새로 추가하기
ESC + L : 해당 줄에 숫자
Ctrl + Shift + P : Help (도움말)
복습 시간 18시 15분 ~ 19시 30분 / 총 1시간 15분
2019년 4월 30일 화요일 2nd
자료형은 총 20가지가 있지만 13가지를 배울 것이다.
자료형
1 2 3 4 5 6 7 8
1. 숫자형 [Integer, Float, Boolean, Complex] 2. 문자형 [String, Bytes, Bytearray] 3. List 4. Tuple 5. Set 6. Frozenset 7. Dictionary 8. Range
정수형을 표현하는 4가지 방법
2진수
0b를 숫자 앞에 붙인다.
8진수
0o를 숫자 앞에 붙인다.
16진수
0x를 숫자 앞에 붙인다.
10진수
아무것도 안쓰면 그냥 10진수이다.
정수형 숫자 범위
1 2 3 4 5 6 7 8 9 10 11 12
import sys sys.maxsize
결과: 9223372036854775807 정수형에서 오버플로우가 없다고 했는데..? 실제로 메모리에 할당 가능한 최대 숫자 크기가 저 값이고 초과되었을 때 동적으로 추가 할당이 된다.(?)
sys.int_info
sys.int_info(bits_per_digit=30, sizeof_digit=4) 32비트 python인 경우, 정수는 최대 30비트까지 허용된다?
진법 변환 builtin
bin() => 2진법으로 변환
oct() => 8진법으로 변환
hex() => 16진법으로 변환
2, 8, 16진법의 숫자를 입력하면 자동으로 10진수로 변환
bold채가 아닌데 색이 변하는 것은 builtin함수
float
부동소수는 소수점이 존재하는 수
예외적으로 무한대와 숫자가 아닌 경우도 포함한다
컴퓨터의 부동소수 연산은 정확하지 않은 근사값을 보여준다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
float('inf') => inf (infinity) float('nan') => nan (not a number) # 무한대 개념은 딥러닝에서 미분의 개념을 꼭 알아야 하는데 이때 중요하게 작용한다. 파이썬은 이처럼 숫자 체계가 범위가 넓기 때문에 인공지능에 이용되는 장점이 있다.
# 부동소수 연산 a = 1.7976931348623157e+308 a a + 1 a = a + 1
단, 음수 나눗셈은 주의 해야 한다. ex) 10 // -3 => -4 why? --> -4 + 0.66667 이런식으로 간주하기 때문에
자료형을 구별하는 기준
1 2 3 4 5 6 7 8 9 10 11 12 13
┌─ Mutable # 추가, 삭제가 가능한 경우 / 특징 : 메모리 번지 안바뀜, 재할당할 필요없음 └─ Immutable # 추가, 삭제가 불가능한 경우 / 특징 : 재할당으로 메모리 번지 바뀜
Container ┌─ Homogeneous # 요소들이 서로 같은 타입인 경우 └─ Heterogeneous # 요소들이 서로 다른 타입이 가능한 경우 (요소가 1개 이상인 데이터 구조)
Sequence ┌─ Indexing # 요소를 하나씩 출력 └─ Slicing # 요소를 한번에 여러개 출력 (순서가 있음) Lookup ┌─ Mapping hash # key값과 value를 갖는 Dictinary가 갖는 특징 └─ set # 순서가 없는 고유한 원소들의 집합 (key값으로 이루어진 데이터 구조)
a = '정지혁' a[0:3] or a[:3] :'정지혁' a[-3:] or a[0:] :'정지혁' a[0:3:2] # 양수일때 (맨 뒤에 오는 숫자 - 1) 을 하면 건너 뛰는 문자의 개수를 나타낸다 :'정혁' a[::-1] # 음수일때 |맨 뒤에 오는 숫자 + 1|을 하면 건너 뛰는 문자의 개수를 나타내고 거꾸로 출력한다. :'혁지정' a[:-3:-1] :'혁지' a[:70] # 슬라이싱은 범위가 벗어나도 에러가 나지 않는다 :'정지혁'
Statement는 예약어와 표현식을 결합한 패턴이다.
그리고 실행가능한 최소의 독립적인 코드 조각을 일컫는다. Statement는 총 5가지 경우가 있다.
1. 할당 (Assignment)
2. 선언 (Declaration)
3. 조건 (if)
4. 반복문 (for, while)
5. 예외처리
for문으로 변수 할당하기
1 2 3 4 5
# statement for i in range(1, 20+1): exec('r' + str(i) + '=' +str(i))
# r1, r2 ...r20 까지 1,2,...20 할당
기타 내장 함수
1 2 3 4
dir(obejct) : 어떠한 객체를 인자로 넣어주면 해당 객체가 어떤 변수와 메소드를 가지고 있는지 출력을 합니다. type(object) : 어떠한 객체를 인자로 넣어주면 해당 객체의 타입을 반환한다. len(object) : 어떠한 객체를 인자로 넣어주면 해당 객체의 요소 갯수를 반환한다. id(object) : 해당 객체가 저장되어 있는 메모리 위치를 반환한다.
# 정수형과 리스트를 in 연산을 했을 때는 타입이 달라도 가능하지만 # 정수형과 문자형은 불가능하다 # 기본적으로 멤버쉽 연산자(in)는 container에서만 쓸 수 있고 문자열 일때는 문자열 끼리만 가능하다.
Error
NameError
값을 할당하지 않은 식별자를 사용했을 때 발생하는 에러
IndexError
인덱스 값에서 벗어난 인덱스를 사용했을 때 발생하는 에러
TypeError
서로 다른 타입간의 연산을 했을 경우 발생하는 에러
KeyError
dictionary에서 없는 key값으로 접근할때 발생하는 에러
AttributeError
존재하지 않는 Attribute에 접근하려고 할 때 발생하는 에러
UnboundLocalError
할당하기 전에 지역변수를 참조했을 때 발생하는 에러
복습 시간 18시 35분 ~ 20시 5분/ 총 1시간 30분
2019년 5월 2일 목요일 3rd
할당문의 종류 6가지
1 2 3 4 5 6 7 8 9 10 11 12
1. 기본 할당문 - a = 1 2. Chain assignment - a = b = 1 3. Augmentation - a += 1 4. Pakcing 5. Unpacking - Container 쪼개기 6. Global , nonlocal - global 이용하여 전역번수 접근, 변경하기 # 추천하지 않는 기능 - nonlocal은 함수 중첩시 함수와 함수 사이 변수
# Positional + Keyword # defname(a,b): ''' 함수 설명 '''# Docs String => Shift + Tab 하면 설명이 그대로 나온다 return a, b # 참고로 함수 설명에 ( / )가 있을 경우 Positional 방식이라는 뜻 name(1,2) :(1,2)
# Variable Positional + Variable Keyword # defname(*b, **a): return b, a name(2,3,4,5, a = 9, b = 3, c = [1,2]) # !주의! keyword를 쓰기 시작하면 끝까지 keyword를 써야한다 :((2, 3, 4, 6), {'a': 9, 'b': 3, 'c': [1, 2]})
Positional Only 사용자가 직접 만드는 함수의 파라미터에는 Positional only 방식을 사용할 수 없다. 하지만 기본 내장 함수 중에 파라미터 부분에 / 표시가 되어 있는 경우는 Positional Only 방식을 사용하라는 의미 이다. (shift + tab으로 설명 볼때), (앞으로 python 3.8부터는 positional only 방식을 지원한다고 한다.)
Python에서는 Parameter로 받아 올때 Type을 지정해주지 않는다. Why? Python 철학중 EAFP라는 것이 있는데 이는 ‘허락보다는 용서를 구하기 쉽다’로 부부관계를 예시로 설명하면 이해하기 쉽다. 결혼하고 나면 보통 남자든 여자든 비싼 사치품을 사는 것이 쉽지 않다. 이때 사치품을 사려고 하는 입장의 사람은 결정해야한다. 사고 혼날 것인가. 허락을 받을 것인가. 전자가 더 실행하기 쉽고 빠르다는 것이 Python의 철학인 것이다.
Python Tip1 파이썬은 오버로딩이 안된다.(@연산자로 오버로딩 가능해졌다?) 즉, 같은 함수 이름을 여러개 정의하여 매개변수를 달리하여 사용하는 기법이 허용이 되지 않는다. 파이썬의 단점 중에 속도가 느리다는 점이 있었는데, 오버로딩을 지원하지 않음으로써 속도를 개선했다. (단, 오버라이딩은 사용 가능하다. (매소드 재정의))
1. return이 반드시 있어야 한다 - python에서는 return을 생략하면 None을 반환하도록 되어 있다 2. 함수 안에 또 다른 함수를 선언할 수 있다 3. Global, Local - 함수 안에 없는 값을 return 하게 될 경우 가까운 Global 식별자를 return - Global 식별자이름 하게 되면 접근, 수정이 가능하다 - 함수 밖에서 함수 안의 식별자에 접근, 수정이 불가능하다
함수안의 함수
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
defa(): defb(): return3 return b
a() :<function __main__.a.<locals>.b()> a()() :3
defa(): defb(): return3 return b()
a() :3
# 둘의 차이가 있다 위에것은 함수를 리턴하는 것이고 밑에꺼는 함수 안에서 함수를 호출하여 값을 리턴
Python Tip2 return 값이 있는지 없는지 확인하는 방법 1. type() 2. 값을 저장해서 확인하기
Python Tip3 함수를 리스트에 넣어서 계산을 편리하게 할 수도 있다.
Python Tip4 jupyter에서는 두 가지로 호출할 수 있는 함수인지 판단 가능 1. callable 2. 출력
Python Tip5 Python keyword는 총 35개다.
1 2 3 4 5 6 7
import keyword
cnt = 0 for x in keyword.kwlist: cnt += 1 print(cnt) :35
신기한 함수
1 2 3 4 5
import matplotlib.pyplot as plt
plt.plot([1,2,3,4,5],[9,3,7,3,9])
# 설명에서 plot[x] => 여기서 [] 대괄호는 리스트가 아니고 옵션이라는 뜻
추가 공부
동적 프로그래밍에 대해서 찾아보기
피보나치 다른 방법 공부해보기
과제란에 올려주시는거 문제 풀어보기
여태까지 공부했던건 tree형태로 가지치기 map 그려보기
Python 철학 처음부터 끝까지 정독해보기
복습 시간 17시 28분 ~ 19시/ 총 1시간 32분
2019년 5월 7일 화요일 5th
<First class function/Higher order function 관계 그림 수정>
integer = [1,-1,4,0,44,-34,-42,14] ['양수'if i > 0else ('음수'if i < 0else0) for i in integer] list(map(lambda i: '양수'if i > 0else ('음수'if i < 0else0), integer))
: ['양수', '음수', '양수', 0, '양수', '음수', '음수', '양수']
# 조건식 + 반복식 vs 반복식 + 조건식
li1 = [x if x%2==0elseNonefor x in range(10)] li1 : [0, None, 2, None, 4, None, 6, None, 8, None]
li2 = [x for x in range(10) if x%2==0] li2 : [0, 2, 4, 6, 8]
# 조건식이 왼쪽에 있을때 오른쪽에 있을때 사용법에 있어서 차이가 있으니 조심하자 # 기본적으로 파이썬은 왼쪽에서 오른쪽으로 실행!
# 1 defxx(y, x=[]): return x.append(y) # 사실 엉터리 코딩 x.append(y)는 None을 리턴하고, # 함수 밖에서 x 리스트에 접근도 할 수 없기 때문에 but 인자에 기본값 x list 말고 # 외부에 선언된 list 넣으면 list 확인 가능 # default값을 mutable로 사용하면 heap영역에 들어간다
# 1-1 defxx(list): return list.append(3) x = [1,2] xx(x) x : [1,2,3]
# 2 defxx(y, x=[]): x.append(y) return x # xx함수를 호출 할때마다 x 리스트가 계속 변한다
defxx(y): x = [] x.append(y) return x # xx함수를 호출하면 원소가 하나인 리스트 반환
파이썬 변수의 유효 범위(Scope)
유효 범위 규칙(Scope Rule)은 변수에 접근 가능한 범위, 변수가 유효한 문맥범위를 정하는 규칙
LEGB
1 2 3 4 5 6 7 8
1. Local : 함수 내 정의된 지역변수 2. Enclosing Function Local : 함수를 내포하는 또다른 함수 영역 - 함수 안의 함수가 있는 경우 함수와 함수 사이 3. Global : 함수 영역에 4. Built-in : 내장 영역 - 함수 안의 함수가 있는 경우 함수안의 함수에서 함수 밖의 변수를 사용?
우선순위 => L > E > G > B
LEGB 우선순위 확인 예제
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
x = 'global' defouter(): #x = "local"
definner(): #nonlocal x #x = "nonlocal" #print("inner:", x) return x
inner() #print("outer:", x) return x
outer()
Python Tip5 함수 중첩은 3번 이상 하지 않는 것이 좋다.
신기한 기능
1 2 3 4 5 6
import seaborn as sns tips = sns.load_dataset('tips')
tips.head(10) # 앞에 10개만 보여줘 tips.tail(10) # 뒤에 10개만 보여줘 tips.sample(10, replace = True) # 랜덤으로 10개 보여줘
랜덤 10개
추가공부
변수, 인자와 힙, 스택간의 관계
복습 시간 19시 10분 ~ 21시 40분 / 총 2시간 30분
2019년 5월 9일 목요일 6th
함수형 패러다임
멀티 프로세싱 기법에 최적화된 패러다임
빅데이터 처리시 효율적이다
함수형 프로그래밍의 특징
1 2 3 4 5 6 7 8 9
1. 코드가 간결해진다 - 내부 구조를 몰라도 input, output만 알면 사용 가능 2. 수학적으로 증명이 가능하다 3. for, while문을 자제하고 iter를 사용한다 4. 수학적 증명이 필요하기 때문에 구현이 어렵다 - 단, python에서는 multi paradiam이기 때문에 적절히 혼용 가능 5. 디버깅, 테스트가 용이하다 6. 모듈성, 결합성이 있다. 7. mutable은 처리하지 않는다
반복을 줄이는 5가지 방법
(for문을 최대한 쓰지 않고)
1 2 3 4 5 6 7 8 9
1. Iterator - 메모리 효율적, 속도 빠름 - 실행시에 메모리 할당 2. Generator 3. Comprehension - for를 쓰지만 for를 쓰지 않는 기법 4. Recursive function - 메모리 효율, 속도면에서 성능이 좋지않아 사용안함 5. map, filter, reduce
iterable 1. iterator로 바꿀 수 있는 2. 순회, 반복가능 (요소 하나씩 뽑아냄) 3. for 뒤에 사용할 수 있는 container
왜 함수형 패러다임에서 반복을 줄여야 하는가?
for문 처럼 대입하는 것은 함수형 패러다임에 맞지 않고 수학적 증명과는 거리가 있기 때문이다.
Iterator
데이터 스트림을 표현하는 객체, next()메소드를 사용하여 다음 요소를 가져온다
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
a = [1,2,3] b = iter(a) next(b)
:1 # 실행할 때마다 index 0번지 부터 하나씩 뽑아낸다
# iterator를 객체화하면 iterator의 성질도 잃고 객체화 하기 전 iterator의 요소 전부를 뽑아냄으로 주의! a = [1,2,3] b = iter(a) next(b) : 1 list(b) # tuple(b), set(b) 다 똑같음 : [2,3] next(b) : StopIteration
add3 = partial(add,3) # add의 두개 인자중 하나를 3으로 대체 add3(7) : 10
Python Tip1 locals(), globals() 함수는 함수내에서 사용하면 메모리상에 올라간 local, global 변수를 각각 확인 할 수 있다
1 2 3 4 5 6 7 8 9 10 11 12
x = 10 defa(): y = 20 defb(): a = 1 print(locals()) b = 2 return b() a() :{'a':1} # b = 2는 print문 출력 이후에 있기 때문에 locals에 포함되있지 않다 선언할 때는 모든 것이 메모리에 할당 되지만 실행할때는 순서대로 할당되기 때문이다
name, namespace, module 그리고 name
name은 말 그대로 이름을 붙여주는 즉, 변수명 혹은 식별자라고 생각하면 된다
module은 파이썬 코드를 담고 있는 파일이다, 좀 더 자세하게 말하면 클래스, 함수, 변수명의 리스트가 들어 있다고 보면 된다
namespace는 names(변수명들)을 담을 수 있는 공간이다, 모듈은 자신의 유일한 namespace를 갖고 있으며 모듈의 namespace이름은 보통 모듈이름과 같다. 그래서 동일한 모듈내에서 동일한 이름을 가지는 클래스나 함수를 정의할 수 없다. 또한 모듈은 각각 독립적이기 때문에 동일한 이름을 갖는 모듈을 갖을 수 없다.
> import를 통해 namespace와 __name__에 대해서 자세히 알아보자
import 방법은 3가지가 있다
1 2 3 4
1. import <module_name> - 모듈의 name을 prefix로 사용함으로써 모듈의 namespace에 접근할 수 있다 2. from <module_name> import <name,> 3. from <module_name> import *
쉽게말해 프로그래밍으로 구현될 대상, 현실에 존재하거나 상상가능한 대상을 특징지어 구현될 대상이라고 할 수 있다
그리고 python 프로그램의 모든 data는 객체나 객체간의 관계로 표현된다
John von neumann’s stored program computer model을 따르고 또 그 관점에서 코드 역시 객체로 표현된다
객체를 구현하려면?
객체를 구현하기 위한 설계도 및 틀을 Class(클래스)라고한다
Class를 실제로 프로그래밍할때 사용하려면 클래스 선언, 메모리 할당, mapping 3가지 단계가 필요하다
이해를 돕기 위해 java의 경우를 예로 들겠다
1 2 3 4 5 6 7 8 9 10 11 12 13 14
package test;
import test.Add; // 1. 선언된 클래스 import (클래스 선언)
publicclassTest{ publicstaticvoidmain(String[] args){ Add add = null; // 참조변수 선언 add = new Add(); // 참조변수에 인스턴스에 대한 참조(참조값) 할당 //Add add = new Add(); 위와 동일 // 메모리에 생성되어 저장된 객체 처리 가능 // add는 레퍼런스 변수, 인스턴스를 가리키는값 // 참조변수를 사용하여 멤버변수, 메소드 접근가능 System.out.print(add.sum(3,4)); } }
1 2 3 4 5 6 7
1. 클래스 사용을 위해 클래스 선언 2. 클래스 사용시 메모리에 생성 3. Index table에 참조변수와 메모리 연결을 위한 주소를 매핑하는 참조값이 만들어진다 4. 참조값은 JVM이 자동적으로 생성 5. 참조값을 사용하게되면 참조값에 연결된 메모리 즉, 인스턴스를 사용한다는 것
참조 ≒ 참조값(Hash code)
그렇다면 Python에서 객체의 의미를 살펴보자
1 2 3 4 5 6 7 8 9 10 11 12 13 14
a = 1 print(type(a)) a = 3.2 print(type(a)) print(a) a.__class__
: <type 'int'> <type 'float'> 3.2 int
# Python에서는 선언과 할당을 동시에 하면서 # 할당값에 의해 변수의 타입(객체의 타입)이 결정되고 naming된 변수 이름이 인스턴스가 되는 것이다
A.x # 클래스로 클래스 변수 접근 a = A() # 인스턴스 생성 a.x # 인스턴스 a로 x(클래스 변수)접근 vars(a) # 인스턴스 변수 확인 a.a(3) # 인스턴스 a로 a() (메소드) 접근 vars(a) A.a(a,5) # 클래스로 인스턴스 a와, 5을 인자로 넘겨주고 a함수 접근 vars(a) # 인스턴스 변수는 인스턴스마다 고유로 갖을 수 있는 변수 이다
: Access class TypeError classB: x = 2 defb(self): print('Access instacne')
B.b() b = B() b.b() B.b(b)
: TypeError Access instance Access instance
Instance (인스턴스)
클래스를 사용하려면 인스턴스화 해야한다
인스턴스는 클래스의 값과 메소드에 접근이 가능하다
1 2 3 4 5 6 7 8 9 10 11 12
classA(object):# 기본적으로 class는 object라는 클래스를 상속받는다 # 명시하지 않아도 default로 상속한다 def__init__(self): print('init') # object는 공통적인 속성들을 모아둔 class(추상화, 상속) # init은 내부적으로 인스턴스화 할때 호출함 / 생성자라고도 한다 # init의 추상화 내용이 마음에 들지 않는 경우 변경 가능함(다형성)
A() # 클래스를 호출하면 인스턴스 객체를 반환한다 : init <__main__.A at 0x23b6c143a90> a = A() # 클래스를 호출함으로써 인스턴스 할당 # 인스턴스화를 하면 클래스에 정의되어 있는 기능 사용할 수 있다
defadd5(self, x):# 클래스 내에 다른 함수를 호출 가능 self.add(x+5) return self.array
pop_method = out
array = Array()
array.add(1) array.add(2) array.add(3)
vars(array) : {'array': [1, 2, 3]}
array.pop_method(0) : [2, 3]
vars(array) : {'array': [2, 3]}
array.array : [2, 3]
array.add5(1) : [2, 3, 6]
classmethod, staticmethod
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classA: a = 1 def__init__(self,y): self.y = y defgetx(self): return self.y
@classmethod defgetxx(cls):# class method print('a')
@staticmethod # 똑같이 함수 처럼 사용 defy(cls): print('b')
객체 지향의 특징
1 2 3 4 5 6 7 8 9 10 11 12
1. 캡슐화 - 재활용 가능 - 파이썬에서는 기본적으로 외부에서 클래스 접근 가능 - descriptor로 클래스 접근을 막을 수도 있다 2. 추상화 - 구체적인것과 추상적인 것을 분리시킨다 - 특징을 뽑아 객체로 구현 3. 상속 - 추상화의 반대 - 추상화한 클래스를 물려받아 구체적으로 원하는 대로 바꾸어 사용 가능 4. 다형성 - 다양한 결과를 낼 수 있다
Python Tip1 유지보수를 해야 한다고 느끼면 객체지향 프로그래밍을, 멀티프로세스나 다양한 문제를 다양한 방식으로 풀고 디버깅을 편하게 해야 한다고 느끼면 함수형 프로그래밍을 하면 된다
Python Tip2 동적으로 인스턴스 변수, 메소드 추가 가능 but 좋지 않은 방식
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
# ex) classDyn(): name = 'jh' defname(self): print('nothing') dy = Dyn() dyn.d() vars(dy) dy.name dy.name = 'jane' dy.name vars(dy)
def__init__(self, number, status): self.number = number self.status = status
@classmethod defknock(cls): print("Knock!")
@classmethod defpaint(cls, colour):# 클래스, 인스턴스 모두 사용 가능하고 cls.colour = colour # 클래스 변수 바꾼다 # 클래스로 접근한다 / 클래스만 값에 접근 가능 @classmethod defpaint2(cls, number):# number는 인스턴스 변수 cls.number = number # classmethod는 클래스 변수만 바꿀 수 있다 defopen(self): self.status = 'open'
defclose(self): self.status = 'closed'
classSecurityDoor(Door): pass
Door.knock() door = Door(1, 'open') vars(door) door.knock() door.paint('red') # 인스턴스로 클래스 변수 바꿀 수 있음 (@classmethod) door.colour Door.colour door.paint2(2) door.number Door.paint2(3) # 클래스만 인스턴스 변수 바꿀 수 있음 (@classmethod) door.number Door.number
Python의 철학중 양해를 구하기보다 용서를 구하기가 더 쉽다라는 것이 있다. 이처럼 Python에서 예외처리는 빠질 수 없는 부분이다.
1 2 3
하지만 DataScience 분야에서는 많이 사용하지는 않는다. 웹이나 자동화 등 사용자로부터 입력을 받거나 외부 조건에 의해 오류가 많이 날 수밖에 없는 환경에서는 굉장히 중요하다 따라서 오류가 나더라도 중단하지 않고 실행을 시켜야 하는 경우에 대비해서 예외처리문을 삽입하는 것이다
예외처리 구조
1 2 3 4 5 6 7 8 9 10 11
a = {'a':1} try: t = a['b'] except: # 에러가 나면 실행 / 에러종류에 따라 여러개 만들 수 있음 print('except') else: # 에러가 나지 않으면 실행 print('else') finally: # 에러 상관없이 실행 print('finally')
: <class '__main__.MySpecialClass'> # 인스턴스 msp의 클래스명은 MySpecialClass <class '__main__.MyType'> # 클래스 MySpecialClass의 메타클래스는 MyType <class 'type'> # 메타클래스 MyType의 메타클래스는 type # 따라서 메타클래스를 만들기 위해서 type을 상속받아야 한다 # lambda 함수식 처럼 클래스도 선언없이 사용할 수 있다 A = type('Integer', (int,), {}) # int클래스를 상속받아 A라는 클래스를 생성
a = A(3) a type(a) : 3 __main__.Integer
B = type('List', (list,), {}) b = B([1,2,3]) b type(b) : [1,2,3] __main__.List
C = type('multi', (A, B), {}) : TypeError # multiple bases have instance lay-out conflict # => 상속받으려는 두 클래스의 속성이 비슷하여 충돌이 일어나는 경우 다중 상속이 불가하다. # => 물론 해결하는 방법은 있는 듯 하다
classx: def__init__(self): print('x') classB(x): def__init__(self): super().__init__() print('B') classA(x): def__init__(self): super().__init__() print('A') classC(A,B): def__init__(self): super().__init__() print('C') c = C() : x B A C
점(.)으로 객체의 멤버를 접근할 때, 먼저 인스턴스 변수(dict)에서 멤버를 찾는다. 없을 경우 클래스 변수에서 찾는다. 클래스에서 멤버를 찾고 객체가 descriptor 프로토콜을 구현했다면 바로 멤버를 리턴하지 않고 descriptor 메소드(get, set, delete)를 호출한다