파이썬 어디까지 써 봤니?!
왜 파이썬일까?
파이썬의 성능
if(true) {
System.out.println("첫 번째");
if(true) {
System.out.println("두 번째");
}
}
if True :
print("첫 번째")
if True :
print("두 번째")
컴파일 언어
실행전, 소스코드를 기계어 변환후 파일 실행
기계어를 실행하므로 비교적 빠르다.
컴파일 시점에서 소스코드의 오류를 잡기 쉽다.
같은 소스코드도 다른 환경에서 실행하려면 다시 컴파일해야함
스크립트언어
코드 작성과 함께 인터프리터가 기계어로 번역, 실행
번역 과정이 있어 비교적 느리다.
목적에 뚜렷하게 개발되어 사용하기 쉬운 편
코드줄로 코드 즉시 실행 가능
파이썬을 더 잘 사용해 보자!
2.1 For문 잘 써보기
enumerate() : 문자열 튜플 리스트 등의 순서와 함께 리스크의 값을 반환.
```python
my_list = ['a','b','c','d']
for i, value in enumerate(my_list):
print("순번 : ", i, " , 값 : ", value)
>>>
순번 : 0 , 값 : a
순번 : 1 , 값 : b
순번 : 2 , 값 : c
순번 : 3 , 값 : d
```
이중 for 문 : **`[0, 1]`과 `['a','b','c','d']` 두 리스트를 조합**
```python
my_list = ['a','b','c','d']
result_list = []
for i in range(2):
for j in my_list:
result_list.append((i, j))
print(result_list)
>>>
[(0, 'a'), (0, 'b'), (0, 'c'), (0, 'd'), (1, 'a'), (1, 'b'), (1, 'c'), (1, 'd')]
```
리스트 컴프리헨션(List Comprehension) : 순회형객체에서 이를 가공한 새로운 객체 생성하는 간결한 방법
```python
my_list = ['a','b','c','d']
result_list = [(i, j) for i in range(2) for j in my_list]
print(result_list)
>>>
[(0, 'a'), (0, 'b'), (0, 'c'), (0, 'd'), (1, 'a'), (1, 'b'), (1, 'c'), (1, 'd')]
```
제너레이터(Generator) : 데이터를 전부 메모리에 올려두지 않고, 현재 처리할 데이터를 1개씩 로드하여 사용. 빅데이터를 다룰 머신러닝에서 요긴하다.
예) 단순 이중 for 문을 사용할 경우 이다. result_list 에 모든 데이터가 담기길 기다렸다가 반환받는다.
```python
my_list = ['a','b','c','d']
# 인자로 받은 리스트를 가공해서 만든 데이터셋 리스트를 리턴하는 함수
def get_dataset_list(my_list):
result_list = []
for i in range(2):
for j in my_list:
result_list.append((i, j))
print('>> {} data loaded..'.format(len(result_list)))
return result_list
for X, y in get_dataset_list(my_list):
print(X, y)
>>>
>> 1 data loaded..
>> 1 data loaded..
>> 1 data loaded..
>> 1 data loaded..
>> 1 data loaded..
>> 1 data loaded..
>> 1 data loaded..
>> 1 data loaded..
>> 8 data loaded..
0 a
0 b
0 c
0 d
1 a
1 b
1 c
1 d
```
예) 제네레이터 yield 를 사용한 코드이다. yield 는 양보라는 뜻으로, 코드 실행의 순서를 밖으로 양보한다.
```python
my_list = ['a','b','c','d']
# 인자로 받은 리스트로부터 데이터를 하나씩 가져오는 제너레이터를 리턴하는 함수
def get_dataset_generator(my_list):
result_list = []
for i in range(2):
for j in my_list:
yield (i, j) # 이 줄이 이전의 append 코드를 대체했습니다
print('>> 1 data loaded..')
dataset_generator = get_dataset_generator(my_list)
for X, y in dataset_generator:
print(X, y)
>>>
0 a
>> 1 data loaded..
0 b
>> 1 data loaded..
0 c
>> 1 data loaded..
0 d
>> 1 data loaded..
1 a
>> 1 data loaded..
1 b
>> 1 data loaded..
1 c
>> 1 data loaded..
1 d
>> 1 data loaded..
```
이처럼, 제네레이터가 없다면 1억짜리 리스트를 리턴받아 메모리에 두고 사용해야하지만, 제네레이터는 사용할 데이터를 1개씩 로드하므로 빅데이터, 머신러닝에 활용가치가 높다.
**2.2 Try - Except**
**에러 처리를 위한 방법이다.** 코드를 수행중 예외(에러)가 발생하면 예외(에러)를 무시하거나 적절한 처리를 하는 작업이다.
![Untitled](https://s3-us-west-2.amazonaws.com/secure.notion-static.com/a6e0ff6d-6c8f-4257-b649-8b378502ca75/Untitled.png)
statements를 수행하다가 에러발생시 except코드를 실행한다.
```python
a = 10
b = 0
try:
#실행 코드
print(a/b)
except:
print('에러가 발생했습니다.')
#에러가 발생했을 때 처리하는 코드
b = b+1
print("값 수정 : ", a/b)
```
**2.3 Multiprocessing**
병렬처리하는 방법을 배워보자
```python
import multiprocessing # 1. multiprocessing 모듈 임포트
import time
num_list = ['p1','p2', 'p3', 'p4']
start = time.time()
def count(name): # 2. 병렬처리할 함수 작성
for i in range(0, 100000000):
a = 1+2
print("finish:"+name+"\n")
if __name__ == '__main__': # 3. '코드의 시작 지점을 여기로 하라' 라는 명령어
# 4. 병렬처리시 4개 프로세스사용 (cpu코어수 만큼 사용시 최대효과)
pool = multiprocessing.Pool(processes = 4)
# 5. 병렬화 함수, count함수에 num_list원소 하나씩 넣어 놓는다.
# count('p1'), count('p2'), count('p3'), count('p4')가 만들어진다.
pool.map(count, num_list)
# 6. 병렬화 끝부분, 더이상 pool로 새로운 추가 작업 않을 때
pool.close()
# 7. 프로세스 종료까지 대기하라는 구문. 병렬처리작업이 끝날 때 까지 기다림.
pool.join()
print("time :", time.time() - start)
```
같은 코드 두 번 짜지 말자!
3.1 함수(Function)
**코드의 효율성, 재사용성, 가독성**
pass문 : 제어흐름도구, 아무것도 하지 않는다. 특별히 할 일이 없을 때 사용
```python
def empty_function():
pass
```
함수에 함수 사용
```python
def say_something(txt):
return txt
def send(function, count):
for i in range(count):
print(function)
send(say_something("안녕!"), 2)
```
함수 안의 함수& 2개 이상의 retrun
**함수 내부에서 정의된 함수는 함수 내부에서만 호출할 수 있다.**
```python
list_data = [30, 20, 30, 40]
def minmax_function(x_list):
def inner_min_function(x):
length = len(x)
min_result = x[0]
for i in range(length):
if min_result > x[i]:
min_result = x[i]
return min_result
def inner_max_function(x):
length = len(x)
max_result = x[0]
for i in range(length):
if max_result < x[i]:
max_result = x[i]
return max_result
x_min = inner_min_function(x_list)
x_max = inner_max_function(x_list)
# 2개 이상의 값을 리스트에 넣어 반환하므로 인덱싱으로 사용하면 된다.
minmax_list = [x_min, x_max]
return minmax_list
print("최솟값, 최댓값은 : ", minmax_function(list_data))
print("최솟값은 : ", minmax_function(list_data)[0])
print("최댓값은 : ", minmax_function(list_data)[1])
```
여러 변수로 받아 반환 할 수도 있다.
```python
....
# , 콤마로 여러값으로 반환하고 이를 받아 각각 활용
return x_min, x_max
min_value, max_value = minmax_function(list_data)
print("최솟값은 : ", min_value)
print("최댓값은 : ", max_value)
```
**3.2 람다 표현식**
익명함수 : 함수를 간결히 한다. 함수며으 return등 틀을 최대한 생량하는 문법. 함수명이 없기 때문에 한번 만들면 다시 호출할 수 없는듯하다.
```python
기존 함수
def 함수명 (매개변수) :
실행코드
return 반환값
함수명(인수)
람다- 익명이라 함수명이 없습니다.
(lambda 매개변수 : 반환값)(인수)
또는
lambda 인자 : 표현식
여기서 반환값, 표현식은 return 값인데,
일반함수에서 실행코드부분도 함께 결합해서 반환값으로 만들어야하는 것같습니다.
```
```python
# 더하기함수 2줄
def add(x, y):
return x + y
# 한줄로 줄이기
def add(x, y): return x + y
# 람다로 만들면?
print( (lambda x,y: x + y)(10, 20) )
#(lambda 매개변수 : 반환값)(인수)
# 매겨변수 : 함수내부
# 인수 : 함수외부에서 매개변수에 전달할 값
```
**인수부분을 간단히 하는 효과!**
```python
# 람다 없이
def list_mul(x):
return x * 2
result = list(map(list_mul, [1, 2, 3]))
print(result)
# 람다 사용
result = list(map(lambda i: i * 2 , [1, 2, 3]))
print(result)
```
map(), filter(), reduce()등과 자주 쓰인다.
**3.3 클래스(Class), 모듈(Module), 패키지(Package)**
클래스(Class) : 비슷한 역할을 하는 함수 집합
모듈(Module) : 함수, 변수, 클래스를 모아놓은 파일. 코드 저장소
패키지(라이브러리) : 여러 모듈을 하나로 모아둔 폴더.
패키지 설치 : pip install 패키지이름
프로그래밍 패러다임과 함수형 프로그래밍
패러다임(Paradigm) : 시대의 사고를 근본적으로 규정하는 테두리
프로그래밍 패러다임 : 프로그래머의 프로그래밍 관점. 결정하는 역할. 여러 프로그램이 패러다임이 존재한다.
절차 지향 프로그래밍 & 객체 지향 프로그래밍
절차 지향 프로그래밍 : 진행 순서로 프로그래밍
장 : 순차적 작성으로 순서대로 읽으면 이해 가능
단 : 위에서 하나라도 잘못되면 연쇄적 문제 발생. 유지보스 어렵다. 코드가 길어 분석이 어렵다.
객체 지향 프로그래밍 : 프로그램을 상호작용하는 객체들의 집합으로 인식. 객체릴 작성하고 함수를 작성. 객체 간의 상호작용.
장 : 코드 재사용, 코드분석 용이. 아키텍처 수정 쉽다.
단 : 객체간 상호작용을 설계에 시간이 소요. 설계를 잘못하면 전체적으로 수정이 필요할 수 있다.
파이썬은 객체지향이다.
파이썬 - OOP Part 1. 객체 지향 프로그래밍(OOP)은 무엇인가? 왜 사용하는가? - schoolofweb.net
함수형 프로그래밍
순수성 : 반환값 이외의 변견상항을 만들지 않는, 부작용이 없는 순수함수
# 순수성이 없는 코드
# 함수 외부의 데이터 A를 사용하기때문
A = 5
def impure_mul(b):
return b * A
print(impure_mul(6))
# 순수성이 있는 함수
def pure_mul(a, b):
return a * b
print(pure_mul(4, 6))
모듈성 : 문제를 작은 조각으로 분해하도록 강제한다. 작은 함수는 가독성이 좋고, 오류 확인이 용이하다.
디버깅, 테스트 용이성 : 각 함수에서 데이터가 바른지 확인할 수 있는 포인트가 된다.
파이써닉하게 코드를 짜보자!
#한 줄의 코드 길이가 79자 이하여야 합니다.
y = a + a + a + a # 79자 이하
#함수와 클래스는 다른 코드와 빈 줄 두 개로 구분합니다.
class a():
pass
# 빈 줄
# 빈 줄
class b():
pass
# 빈 줄
# 빈 줄
def c():
pass
# 빈 줄
# 빈 줄
#클래스에서 함수는 빈 줄 하나로 구분합니다
class a():
def b():
pass
def c():
pass
#변수 할당 앞뒤에 스페이스를 하나만 사용합니다.
y = 1
#리스트 인덱스, 함수 호출에는 스페이스를 사용하지 않습니다.
my_list = [1, 2, 3]
my_list[0] # 리스트 인덱스 호출
my_function(0) # 함수 호출
#쉼표(,), 쌍점(:), 쌍반점(;) 앞에서는 스페이스를 사용하지 않습니다
my_list = [1, 2, 3]; my_list[0:1]
if len(my_list) == 3: print my_list
#변수명 앞에 _(밑줄)이 붙으면 함수 등의 내부에서만 사용되는 변수를 일컫습니다.
_my_list = []
#변수명 뒤에 _(밑줄)이 붙으면 라이브러리 혹은 파이썬 기본 키워드와의 충돌을 피하고 싶을 때 사용합니다.
import_ = "not_import"
#소문자 L, 대문자 O, 대문자 I를 가능하면 사용하지 마세요.
#특정 폰트에서는 가독성이 굉장히 안 좋습니다.
#모듈(Module) 명은 짧은 소문자로 구성되며, 필요하다면 밑줄로 나눕니다.
my_module.py
#클래스 명은 파스칼 케이스(PascalCase) 컨벤션으로 작성합니다.
class MyClass():
pass
#함수명은 소문자로 구성하되 필요하면 밑줄로 나눕니다.
def my_function():
pass
#상수(Constant)는 모듈 단위에서만 정의하고
#모든 단어는 대문자이며, 필요하다면 밑줄로 나눕니다.
MY_PI = 3.14 # 상수는 변하지 않는 변수입니다.
모든 공백을 "_"로 바꾸고 모든 단어는 소문자입니다.
파이썬에서는 함수, 변수 등을 명명할 때 사용합니다.
ex) this_snake_case
모든 단어가 대문자로 시작합니다.
UpperCamelCase, CapWords라고 불리기도 합니다.
파이썬에서는 클래스를 명명할 때 사용합니다.
ex) ThisPascalCase
처음은 소문자로 시작하고 이후의 모든 단어의 첫 글자는 대문자로 합니다.
lowerCamelCase라고 불리기도 합니다.
파이썬에서는 거의 사용하지 않습니다 (Java 등에서 사용)ex) thisCamelCase