무냐의 개발일지
[1/4] 파이썬 기초 본문
파이썬
파이썬이라는 이름은 파이썬의 창시자 귀도 반 로섬이 좋아하는 코미디인〈Monty Python's Flying Circus〉에서 따온 것입니다. 이름에서 고대신화에 나오는 커다란 뱀을 연상하는 경우도 있겠지만 이와는 무관합니다. 다만 로고에는 뱀 두마리가 형상화되어 있습니다
함수와 변수
함수 : 불려진 시점에 특정한 작업을 수행하며, 입력값과 출력값은 있을 수도 없을 수도 있다
def : 함수를 정의(define) 할 때 사용하는 일종의 예약어이며, 함수명은 임의로 만들 수 있다.
에러 IndentationError : 들여쓰기 된 코드 블럭, 즉 indented block을 기대했는데 왜 빼먹었냐는 불평입니다.
전역스코프(global scope), 지역스코프(local scope) : 함수 내에서 정의되는 변수
매개변수(parameter): 입력값으로 주어진 인자(argument)를 받는 변수 (아래 예시에서 name), 땡땡은 인자
say_hi_somebody('땡땡')
입력값이 여러 개일 때 : 각 입력값마다 기본값을 지정해 줄 수 있다.
단, 이 경우 기본값이 있는 인자들이 기본값이 없는 필수 인자들의 뒤에 와야 한다.
제어문
if문 : if, elif, else, 논리연산자(and, or) 등
while문 : 조건이 참인 동안만 반복(루프 loop), 코드 블록을 실행하기 전 가장 먼저 조건문을 검사해서, 조건문이 참이면 코드 블록을 실행
while 뒤에는 참과 거짓이 갈릴 수 있는 명제가 온다
for문 : 하나씩 반복, for 뒤에는 a in A의 형태로, 값이 여러 개 들어있는 목록 A에서 값을 하나씩 꺼내서 a 변수에 담아 반복문을 실행
이렇게 줄줄이 굴비처럼 엮여서 하나씩 순서대로 넘길(iterate) 수 있는 값들을 반복 가능한(iterable, 이터러블) 객체
자료형
정수(integer, int), 부동소수점(float),
참고) 1 + 1.0의 결과와 같이, 정수와 소수를 더하면 그 결과가 소수 자료형을 가지게 된다
참고) 고정소수점 : 소수점의 위치를 고정
NoneType: 어떤 것으로도 정의되지 않는 유형
Boolean: True, False(None/ 0일때)
따옴표를 그대로 쓰고 싶을 때 \ 를 앞에 붙여준다
Quote(') and double quote(")
튜플 ()
: 값 변경 불가, 튜플 안에 튜플 삽입 가능, 색인으로 특정 위치 값 읽을 수 있음, 덧셈으로 합치기 가능, in연산으로 값 존재여부 확인 가능
리스트 []
: 값 변경 가능, append를 통해 삽입, remove로 삭제 가능, pop으로 특정 순서값 삭제 가능
딕셔너리(Dictionary)
: 직접 인덱스를 원하는대로 지정 가능 (key, value묶음)
: 값 추가 가능 (그냥 추가하면 됨)
: 제거 가능 ( .pop(key))
: for 루프문 사용시 키만 반환
: items() 를 쓰면 키, 값 둘다 반환
재귀함수(recursive function)
스스로를 호출하는 함수를 뜻한다. 대표적으로 피보나치 함수가 있다.
퍼포먼스(성능) : 어떤 언어든 코드를 짜서 실행을 시켰을 때 얼마나 빨리 처리가 되는가
생산성 : 똑같은 기능을 하는 프로그램을 얼마나 빨리 작성할 수 있는가
퍼포먼스 & 생산성은 역의 상관관계가 있음 (파이썬 : 퍼포먼스 낮음, 생산성 높음)
파이선의 특징
1. 높은 생산성
2. 간결한 코드
3. 빠른 개발 속도
4. 스크립트 언어 (=인터프리터 언어)
컴파일 언어 :
- 실행 전 소스 코드를 컴파일하여 기계어로 변환 후 해당 파일을 실행
- 이미 기계어로 변환된 것을 실행하므로 비교적 빠름
- 컴파일 시점에 소스 코드의 오류를 잡기 쉬움
- 같은 소스 코드도 다른 환경(PC, mobile 등)에서 실행하려면 다시 컴파일(기계어로 변환) 해야함
스크립트 언어 :
- 코드를 작성함과 동시에 인터프리터가 기계어로 번역하고 실행함
- 코드 번역 과정이 있어 비교적 느림
- 주 사용 목적이 뚜렷하게 개발되어 사용하기 쉬운 편
- 명령줄로 코드를 즉시 실행할 수 있음
For 문 활용
- enumerate() : 리스트, 문자열, 튜플 등이 있는 경우 순서와 리스트의 값을 함께 반환
리스트 컴프리헨션(list Comprehension) : 쉽게 말해, 순회형을 이용해 코드를 한 줄로 짜는 거! 리스트 등 순회형 컨테이너 객체로부터 이를 가공한 새로운 리스트를 생성하는 아주 간결하고 편리한 방법, 셋(Set), 딕셔너리(Dict)에 대해서도 적용 가능
yield : 코드 실행의 순서를 밖으로 "양보"합니다. 즉, dataset_generator = get_dataset_generator(my_list) 을 실행해도 "generator object" 만 반환할 뿐, 저희가 원하는 값을 바로 반환하고 있지 않습니다.
Try-Except 예외 처리
에러를 잡기 위한 방법으로, 예외 처리는 코드를 수행하다가 예외(에러)가 발생했을 때 그 예외(에러)를 무시하게 하거나 예외(에러) 대신 적절한 처리를 해주게 하는 등의 작업
Try 코드 수행 -> 에러 발생 시 Except 내의 코드 실행
a = 10
Multiprocessing
컴퓨터가 작업을 처리하는 속도를 높여주는 방법
-parallel processing (병렬처리) : 동시에 처리시키기
-serial processing (순차처리)
import multiprocessing
#병렬 처리하고싶은 함수
def count(name):
time.sleep(5)
print("finish:"+name+"\n")
num_list = ['p1','p2', 'p3', 'p4']
#코드 시작점을 여기로 하라(main)
if __name__ == '__main__':
pool = multiprocessing.Pool(processes = 2) --> 병렬 처리 시, 2개의 프로세스를 사용하도록 합니다. CPU 코어의 개수만큼 입력해 주면 최대의 효과를 볼 수 있습니다(코어 갯수: 터미널에 grep -c processor /proc/cpuinfo 입력)
pool.map(count, num_list). --> 병렬화를 시키는 함수로, count 함수에 num_list의 원소들을 하나씩 넣어 놓습니다. 여기서 num_list의 원소는 4개이므로 4개의 count 함수에 각각 하나씩 원소가 들어가게 됩니다.
pool.close() --> 병렬화 부분이 끝나면 나옵니다. 더 이상 pool을 통해서 새로운 작업을 추가하지 않을 때 사용
pool.join() --> 프로세스가 종료될 때까지 대기하도록 지시하는 구문
참고) 코드의 실행 시간을 측정하는 방법 : time 함수
5-3. for문 잘 써보기 - enumerate()와 이중 for문
my_list = ['a','b','c','d']
for i, value in enumerate(my_list):
print("순번 : ", i, " , 값 : ", value)
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)
*enumerate() : 리스트, 문자열, 튜플 등이 있는 경우 순서와 리스트의 값을 함께 반환해 주는 기능
참고 - range() • range(start, stop, step) : range(2)와 같이 정수가 들어가야 하며, list() 함수를 통해 값을 뽑아오면 0부터 시작해서 2개인 list ([0, 1]) 를 만듭니다. 즉, stop 까지 포함하지는 않습니다. range(1, 10, 2) 이라면 1부터 9까지 2씩 증가하는 [1, 3, 5, 7, 9] 를 만듭니다. 하지만 실제로 반환하는 타입은 range이며, 리스트로 받아오고 싶다면 list(range(1, 10, 2))를 하시면 됩니다.
이중 for문을 이용하여 아래와 같이 별을 하나씩 추가하여 찍는 코드를 작성해 보세요.
****print('*' * i)****
리스트 컴프리헨션(list Comprehension) : 리스트 등 순회형 컨테이너 객체로부터 이를 가공한 새로운 리스트를 생성하는 아주 간결하고 편리한 방법
5-4. Try - Except 예외 처리하기
a = 10
b = 0
try:
#실행 코드
print(a/b)
except:
#에러가 발생했을 때 처리하는 코드
print('에러가 발생했습니다.')
5-5. Multiprocessing
컴퓨터가 작업을 처리하는 속도를 높여주는 방법
import multiprocessing
import time
num_list = ['p1','p2', 'p3', 'p4']
start = time.time()
def count(name):
time.sleep(5)
print("finish:"+name+"\\n")
if __name__ == '__main__':
pool = multiprocessing.Pool(processes = 2)
pool.map(count, num_list)
pool.close()
pool.join()
print("time :", time.time() - start)
if __name__ == '__main__': 코드 시작점을 여기로 하라는 명령어
pool = multiprocessing.Pool(processes = 2) : 병렬 처리 시, 2개의 프로세스를 사용하도록 합니다. CPU 코어의 개수만큼 입력해 주면 최대의 효과를 볼 수 있습니다. (코어의 개수는 터미널에 grep -c processor /proc/cpuinfo 명령어를 입력하여 확인할 수 있습니다. CPU에 대한 자세한 정보를 알고 싶다면 터미널에 cat /proc/cpuinfo 명령어를 입력하여 확인해볼 수 있습니다.) pool.map(count, num_list) : 병렬화를 시키는 함수로, count 함수에 num_list의 원소들을 하나씩 넣어 놓습니다. pool.close() : 일반적으로 병렬화 부분이 끝나면 나오며, 더 이상 pool을 통해서 새로운 작업을 추가하지 않을 때 사용합니다. pool.join() : 프로세스가 종료될 때까지 대기하도록 지시하는 구문
5-6. 같은 코드 두 번 짜지 말기
함수(Function) : 적어야 하는 양을 줄여준다
def function_f(input_x):
output_x = input_x*input_x
return output_x
최댓값을 구하는 함수
list_data = [10, 20, 30, 40]
list_data2 = [20, 30, 40, 50]
length = len(list_data)
max_result = list_data[0]
for i in range(length):
if max_result < list_data[i]:
max_result = list_data[i]
print("최댓값은 ", max_result)
length = len(list_data2)
max_result = list_data2[0]
for i in range(length):
if max_result < list_data2[i]:
max_result = list_data2[i]
print("최댓값은 ", max_result)
이걸 줄여주면
list_data = [10, 20, 30, 40]
list_data2 = [20, 30, 40, 50]
def 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
print("최댓값은 ", max_function(list_data))
print("최댓값은 ", max_function(list_data2))
장점 : 코드의 효율성, 재사용성, 가독성 향상
5-7. 같은 코드 두 번 짜지 말기
pass
기타 제어 흐름 도구로써, 함수 이름과 입력 정도만 먼저 만들어 놓고 나중에 내부 구현 하고싶을 때 사용 (프로그램이 특별히 할 일이 없을 때 사용)
함수 연달아 사용
def say_something(txt):
return txt
def send(function, count):
for i in range(count):
print(function)
send(say_something("안녕!"), 2)
안녕!
안녕!
함수 안의 함수 & 2개 이상의 return
하나의 함수에서 여러개의 return값을 받고 싶을 때, 함수 안에 함수를 만들 수 있음 (단, 함수 안에서 만든 함수는 해당 함수 내부에서만 사용할 수 있음)
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)
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])
return 되는 것은 minmax_list 1개이지만 그 안에 2개의 값을 넣어놨기 때문에 2개 이상을 반환하는 것과 같은 효과를 보게 되는 것
여러 변수로 반환하기
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)
return x_min, x_max
min_value, max_value = minmax_function(list_data)
print("최솟값은 : ", min_value)
print("최댓값은 : ", max_value)
제너레이터(Generator) : 많은 데이터를 더 효율적으로 구현
my_list = ['a','b','c','d']
# 인자로 받은 리스트로부터 데이터를 하나씩 가져오는 제너레이터를 리턴하는 함수
def get_dataset_generator(my_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)
print(f'메모리 사용량 : {sys.getsizeof(dataset_generator)}')
,(콤마)를 이용해 여러 개의 값을 반환
5-8. 같은 코드 두 번 짜지 말기 (3) 람다 표현식
람다 표현식: 한 줄의 식 형태로 되어 있음
def add(x, y):
return x + y
print( (lambda x,y: x + y)(10, 20) )
<aside> 💡 print( (lambda x,y: x + y)(10, 20) )
</aside>
x, y 는 입력값을 의미합니다.
x + y는 return 부분과 같습니다
- map() 함수는 입력받은 자료형의 각 요소가 함수에 의해 수행된 결과를 묶어서 map iterator 객체로 출력하는 역할 : map(f, iterable)
def list_mul(x):
return x * 2
result = list(map(list_mul, [1, 2, 3]))
print(result)
이렇게 한 방에 각각 multiply를 해준다
result = list(map(lambda i: i * 2 , [1, 2, 3]))
print(result)
filter(), reduce() 등 람다 표현식과 자주 쓰이는 함수가 많이 있습니다.
# Q. filter()와 lambda를 활용해서 다음 nums 변수에 담겨있는 숫자 중 홀수만 출력해보세요.
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
list(filter(lambda n : n%2 != 0 , nums))
5-9. 클래스, 모듈, 패키지
클래스 : 비슷한 역할을 하는 함수들의 집합
class all_calc():
def __init__(self, a, b):
self.a = a
self.b = b
def add(self):
return self.a + self.b
def mul(self):
return self.a * self.b
def sub(self):
return self.a - self.b
def div(self):
return self.a / self.b
모듈 : 함수, 변수, 클래스를 모아 놓은 파일 (이미 만들어져 있는 모듈을 가져와 쓸 수도 있고 아니면 우리가 직접 모듈을 만들어서 사용할 수도 있다)
# mycalculator.py
test = "you can use this module."
def add(a, b):
return a + b
def mul(a, b):
return a * b
def sub(a, b):
return a - b
def div(a, b):
return a / b
패키지 : 패키지(=라이브러리)는 전 세계의 파이썬 사용자들이 만든 유용한 프로그램을 모아 놓은 보물 주머니로, 거의 모든 패키지는 pip 명령어를 통해서 설치 가능
pip install pandas
https://pypi.org/ 여기 사이트에서 패키지 검색해서 다운로드 받을 수 있음
5-10. 프로그래밍 패러다임과 함수형 프로그래밍
패러다임(Paradigm) : 어떤 한 시대의 사람들의 견해나 사고를 근본적으로 규정하고 있는 테두리. 프로그래머에게 프로그래밍의 관점을 갖게 해 주고, 결정하는 역할을 함.
- 절차 지향 프로그래밍
일이 진행되는 순서대로 프로그래밍하는 방법
-장점 : 코드가 순차적으로 작성되어 있어 순서대로 읽기만 하면 이해가 가능합니다.
-단점 : 순차적으로 작성되어 있기 때문에 위에서 하나가 잘못되면 아래도 연쇄적으로 문제가 생겨서 유지 보수가 어렵습니다. 일반적으로 코드 길이가 길어서 코드를 분석하기 어렵습니다.
- 객체 지향 프로그래밍(Object Oriented Programming)
개발자가 프로그램을 상호작용하는 객체들의 집합으로 볼 수 있게 함
-장점 : 코드를 재사용하기 쉽습니다. 코드 분석이 쉬우며 아키텍처를 바꾸기 쉽습니다.
-단점 : 객체 간의 상호작용이 있기 때문에 설계에서 많은 시간이 소요되며 설계를 잘못하면 전체적으로 바꿔야 할 수도 있습니다.
데이터 사이언티스트에게 적합한 프로그래밍 패러다임
-장점 : 함수형 프로그래밍은 효율성, 버그 없는 코드, 병렬 프로그래밍
1)순수성 : 그냥 함수 안에만 있는 변수만 가지고 결과내는거
부작용이 전혀 없는 함수를 순수함수라고 한다. 순수성이 있는 함수는, 함수 안에 함수 밖에서 바로 가져오는 함수나 아니면 밖에 있는 변수를 변경시키는 코드가 없습니다
2)모듈성 : 문제를 작은 조각으로 분해하여, 한 가지 작업을 수행하는 작은 함수들로 쪼개어 만드는 것
3)디버깅 & 테스트 용이성 :
5-11. 파이써닉하게 코드를 짜보자 (https://pep8.org/#code-lay-out)
코드 스타일 가이드 pep8 을 따른다
변수 할당 앞뒤에 스페이스를 하나만 사용
리스트 인덱스, 함수 호출에는 스페이스를 사용하지 않습니다.
쉼표(,), 쌍점(:), 쌍반점(;) 앞에서는 스페이스를 사용하지 않습니다.
변수명 앞에 _(밑줄)이 붙으면 함수 등의 내부에서만 사용되는 변수를 일컫습니다. _my_list = []
변수명 뒤에 _(밑줄)이 붙으면 라이브러리 혹은 파이썬 기본 키워드와의 충돌을 피하고 싶을 때 사용합니다. import_ = "not_import"
함수와 클래스는 다른 코드와 빈 줄 두 개로 구분
클래스에서 함수는 빈 줄 하나로 구분
소문자 L, 대문자 O, 대문자 I를 가능하면 사용하지 마세요
모듈(Module) 명은 짧은 소문자로 구성되며, 필요하다면 밑줄로 나눕니다. my_module.py
클래스 명은 파스칼 케이스(PascalCase) 컨벤션으로 작성 class MyClass():
함수명은 소문자로 구성하되 필요하면 밑줄로 나눕니다. def my_function():
-네이밍 컨벤션(Naming convention)
snake_case
모든 공백을 "_"로 바꾸고 모든 단어는 소문자입니다.파이썬에서는 함수, 변수 등을 명명할 때 사용합니다.
ex) this_snake_case
PascalCase
모든 단어가 대문자로 시작합니다.
UpperCamelCase, CapWords라고 불리기도 합니다.
파이썬에서는 클래스를 명명할 때 사용합니다.
ex) ThisPascalCase
camelCase
처음은 소문자로 시작하고 이후의 모든 단어의 첫 글자는 대문자
lowerCamelCase라고 불리기도 합니다.
파이썬에서는 거의 사용하지 않습니다 (Java 등에서 사용)
ex) thisCamelCase
'Data Scientist Bootcamp' 카테고리의 다른 글
[1/8] 파이썬 계좌 만들기! (0) | 2024.01.09 |
---|---|
[1/5] 클래스 개념, 주사위 만들기 (0) | 2024.01.05 |
[1/3] 깃허브, 협업의 필수 툴! (1) | 2024.01.05 |
[1/2] 데이터 사이언스 첫걸음 (우분투/ 리눅스 기본) (1) | 2024.01.03 |
<모두의 연구소> 데이터 사이언티스트 부트캠프 1기 시작 (2) | 2023.12.29 |