Study/Python

파이썬 라이브러리 활용 프로젝트 - 파이썬 개념 용어 이해

김 도경 2024. 10. 7. 19:51

[2024.10.07] 필수 온라인 강의 Part1 파이썬 라이브러리 활용 프로젝트 CH01 파이썬 라이브러리의 이해

 

인코딩과 디코딩

 


인코딩(Encoding) = 코드화 = 암호화 = 부호화

  • 인코딩 : 컴퓨터에서 인코딩은 동영상이나 문자 인코딩 뿐 아니라 사람이 인지할 수 있는 형태의 데이터를 약속된 규칙에 의해 컴퓨터가 사용하는 0과 1로 변환하는 과정
  • 'ASCII', 'URL인코딩', 'HTML인코딩', 'Base64인코딩', '유니코드(https://home.unicode.org/) 인코딩' 등이 존재
a = "Life is too short"
type(a)                       -> str 형식

b = a.encode('utf-8')       # utf-8 인코딩 (가장 많이 사용되는 유니코드 인코딩)
type(b)                       -> bytes 형식
b = b'Life is too short'
# 한글 인코딩 예시
a = '한글'
a.encode('utf-8')                 -> b'\xed\x95\x9c\xea\xb8\x80' 출력

 

디코딩(Decoding) = 역코드화 = 복호화

b.decode('utf-8')                 -> '한글'

b.decode('ascii')          # 다른 디코더로 디코딩할 시 : 에러 발생 : 디코드 에러 - 꼭 인코딩했던 걸로 디코딩하기

- 꼭 인코딩 했던 언어로 디코딩을 해야한다 : 아니면 UnicodeDecodeError 발생

  • 소스 코드의 인코딩 디코딩
      - 소스 코드 파일이 현재 어떤 방식으로 인코딩되었지 명시하는 방법
      - 파이썬 셸이 아닌 편집기로 코딩할 때는 소스 코드의 인코딩이 매우 중요
#-*- coding: ascii -*-
a = '한글이 보입니다!'

  - Python 2.X 버전은 ascii 가 기본 인코딩 방식

# -*- coding: utf-8 -*-
a = '한글이 보입니다!'

  - Python 3.0 부터는 utf-8 이 기본 인코딩 방식

 

클로저와 데코레이터

 

클로저(Closure) : 함수 안의 함수를 결과로 반환할 때, 그 내부 함수를 클로저(Closure) 라고 합니다.
             - 사용되는 곳 : 콜백(Callback) 함수에 사용, 함수의 순차적 실행, 데코레이터 함수

  • 클래스(Class) 사용하기
class Mul:                       # 클래스 생성
    def __init__(self, m):       # 클래스를 생성하는 함수 __init__
        self.m = m               # init을 받아서 내부함수 m에 저장을 한다는 의미

    def mul(self, n):
        return self.m * n
        
        
if __name__ == "__main__":     # 파이썬프로그램을 만들고 모듈을 실행시킬때 쓰는 구문 main은 아래를 실행해라는 의미
    mul3 = Mul(3)
    mul5 = Mul(5)

    print(mul3(10))  # 30 출력
    print(mul5(10))  # 50 출력
class Mul:
    def __init__(self, m):
        self.m = m

    def __call__(self, n):   # mul 함수를 __call__ 함수명으로 변경, Mul함수보다 더 간결
        return self.m * n
        
if __name__ == "__main__":
    mul3 = Mul(3)
    mul5 = Mul(5)

    print(mul3(10))  # 30 출력
    print(mul5(10))  # 50 출력

 

  • 클로저(Closure) 사용하기
def mul(m):           # 외부 함수
    def wrapper(n):   # 내부 함수 (클로저)
        return m * n
    return wrapper           # 함수가 두개이므로, return도 2개가 들어거야한다
    
if __name__ == "__main__":
    mul3 = mul(3)    # m = 3 인 wrapper 함수가 mul3 에 저장 
    mul5 = mul(5)    # m = 5 인 wrapper 함수가 mul5 에 저장

    print(mul3(10))  # m = 3, n = 10 인 wrapper 함수가 실행
    print(mul5(10))  # m = 5, n = 10 인 wrapper 함수가 실행

 

 

데코레이터 (Decorator)

  • 꾸미다, 장식하다'라는 뜻으로 함수를 꾸며주는 함수. : 보조적인 함수
  • 함수를 인수로 받는 클로저    : 클로저의 종류 중 하나라고 이해하기
  • @를 이용한 어노테이션으로 사용
  • 사용되는 곳 : 반복되는 작업을 여러 함수에 적용할 경우, 기존 함수를 수정하지 않고 추가 기능을 구현하고 싶을 경우
import time

def func1(a, b):                  #func1 함수에 a와 b라는 인자를 받아서, 
    start = time.time()
    print("함수가 실행됩니다.")
    
    val = a + b                   #두개의 인자를 더해서 출력하는 함수 
    
    end = time.time()             # 함수 실행 시간을 측정
    print("함수 수행시간: %f 초" % (end-start))     
    
    return val
    
if __name__ == "__main__":
    result = func1(1, 2)
    print(result)
def func2(a, b):              #func2함수는 a와 b라는 인자를 받아서
    start = time.time()
    print("함수가 실행됩니다.")
    
    val = a * b
    
    end = time.time()
    print("함수 수행시간: %f 초" % (end-start))
    
    return val
    
if __name__ == "__main__":
    result = func2(1, 2)
    print(result)

-> 위의 1번 2번 함수가 중복이 되어있다. 이를 해결하기 위해서 데코레이터를 쓰면 된다

 

- 데코레이터 만들기

def func1(a, b):                                  # 각 함수의 메인 기능 만들기
    val = a + b   
    return val

def func2(a, b):
    val = a * b   
    return val
    
 # ''' 실행 시간 측정 데코레이터 '''
def elapsed(func):                                     # 함수를 인풋으로 받는다.
    def wrapper(a, b):
        print('함수가 실행됩니다.')
        start = time.time()
        result = func(a, b)                            # 함수 실행
        end = time.time()
        print("함수 수행시간: %f 초" % (end - start))  # 함수 수행시간
        return result                                  # 함수 실행 결과 반환
    return wrapper

if __name__ == "__main__":
    deco1 = elapsed(func1)          # 1번 함수를 이용하겠다는 의미
    result = deco1(1,2)             # 데코레이터 정의하고 인자에 숫자를 넣어줌
    print(result)

if __name__ == "__main__":
    deco2 = elapsed(func2)          # 2번 함수를 이용하겠다는 의미
    result = deco2(1,2)             # 데코레이터 정의하고 인자에 숫자를 넣어줌
    print(result)
@elapsed           #@를 붙여서 데코레이터를 만들기 -> 따로 데코레이터 정의 없이 바로 함수 사용 가능
def func1(a, b):
    val = a + b   
    return val

@elapsed
def func2(a, b):
    val = a * b   
    return val

if __name__ == "__main__":
    result = func1(1,2)          # 바로 1번 함수 사용가능
    print(result)
    
if __name__ == "__main__":
    result = func2(1,2)          # 바로 2번 함수 사용가능
    print(result)
이터레이터와 제네레이터

 

이터레이터(Iterator) : 집합에서 값을 차례대로 꺼낼 수 있는 객체(Object) 

                                  - for 문을 순회할 수 있는 객체

          - 사용 이유 : 숫자가 아주 많을 경우 미리 만들어 놓는 것 보다
                            그때 그때 필요할 때 값을 뽑아 사용하고 싶을 경우가 대부분의 상황에서 효율적 (메모리 등)
          - 반복 가능 (Iterable) 객체에만 사용 가능

                    - iter() 로 반복 가능 객체 변환

                    -  next() 로 다음값 뽑기

          - 한번 반복하면 다시 사용될 수 없음

for a in [1, 2, 3]:
    print(a)            -> 1, 2, 3 각각이 출력

이터레이터 만들기

a = [1,2,3]
iterator = iter(a)

next(iterator)  # 첫번째 호출   -> 1출력
next(iterator)  # 두번째 호출   -> 2출력
next(iterator)  # 세번째 호출   -> 3출력
next(iterator)  # 네번째 호출   -> StopIteration이라는 에러 발생 : 한번만 쭉 가는 구조

for a in iterator:
    print(a)                 -> 아무것도 출력이 안 됨 : 위에서 다 뽑아서 써서 for문에서 쓸 게 없다는 의미 : 쓰고 싶으면 이터레이터를 재정의해야함

 

제너레이터(Generator)   : yield()

       - 이터레이터 (Iterator) 를 생성해주는 함수

       - 사용이유 : 함수가 하나의 고정된 값을 반환하는 것이 아닌 순차적으로 다른 값을 반환하기 원할 때

def generator():      #generator라는 함수를 만들고
    yield 'a'         #a, b, c를 순차적으로 넣는 함수
    yield 'b'
    yield 'c'
    
next(g)  # 첫번째 호출          -> 'a' 출력
next(g)  # 두번째 호출          -> 'b' 출력
next(g)  # 세번째 호출          -> 'c' 출력
next(g)  # 네번째 호출          -> StopIteration 출력 : 이터레이터는 한번만 출력
def client_count(total_client):                # 제너레이터 사용 예시
    n = 1                                      # n번째 고객을 의미
    for num in range(total_client):
        print(f'{n} 번째 고객님 입장하십시오!')
        n += 1
        yield
        
mygen = client_count(100)
next(mygen)              -> 1 번째 고객님 입장하십시오! 출력
next(mygen)              -> 2 번째 고객님 입장하십시오! 출력
next(mygen)              -> 3 번째 고객님 입장하십시오! 출력

 

 

변수 타입 어노테이션

 

타입 어노테이션 (Type Annotation)

  - 변수나 상수를 선언할 때 그 타입을 명시적으로 선언해 줌으로써 어떤 타입의 값이 저장될 것인지를 직접 알려주는 방법
  - 프로그램은 수많은 함수, 클래스 등으로 복잡하게 얽혀있는 경우가 많음 -> 변수 타입이 맞지 않으면 에러나 버그의 발생 가능성이 높아짐 : 이를 방지하기 위한 사용
 - 사용 시, 코드 가독성과 협업 효율성이 높아짐
 - Python 3.5 부터 기능이 지원되어 많은 라이브러리, 프로젝트에서 사용이 확산되는 추세

 

  • 정적 프로그래밍 언어(statically typed language) :  컴파일 시 변수 타입이 결정됨 ( Java, C, C++ 등)
  • 동적 프로그래밍 언어(dynamic programming language) : 프로그램 실행 도중 변수 타입을 동적으로 바꿀 수 있음(파이썬 등)
    - 장점
         - 타입에 자유로워 유연한 코딩이 가능하므로 쉽고 빠르게 프로그램을 만들 수 있음
         - 타입 체크를 위한 코드가 없으므로 비교적 깔끔한 소스 코드
    - 단점
         - 프로젝트의 규모가 커질수록 잘못된 타입 사용으로 말미암은 버그가 생길 확률 높아짐
         - 타입 어노테이션이 없을 시, 정적 프로그래밍 언어와 타입 버그 발생 시 원인 찾기 어려움
         - 실행속도가 느림
# Python
a = int(1)           #int임

a = str("1")         # int에서 자동으로 str로 바뀜
type(a)

타입 어노테이션을 안해줘도 상관이 없다! 하지만 해주는 게 좋음!! -> 나중에 에러가 날 수 있음

# 파이썬 타입 어노테이션
a: int = 10

a          # -> 10 이 출력
def add(a: int, b: int) -> int: 
    return a + b
     
add(1, 2)         # 3이 출력
add("1", "2")   # 에러가 발생하지는 않음 , 대신 12가 출력 : 문자열 덧셈의 출력

add.__annotations__   # 타입 어노테이션 확인  {'a': int, 'b': int, 'return': int} 출력

 

문자열 처리 - str()과 repr()
  • str() 과 repr() 함수 : 객체를 문자열로 반환하는 함수
      - str() 은 비공식적인 문자열을 출력, 사용자가 보기 쉽도록/ 프로그램 사용자를 위해
      - repr() 은 공식적인 문자열을 출력 (시스템에서 인식가능), 문자열로 객체를 다시 생성/ 프로그램개발자를 위해
a = 123 

str(a)           # '123'출력
repr(a)          # '123'출력

- 숫자의 경우 동일함

a = "Hello World !"

str(a)              # 'Hello World !' 출력
repr(a)             # "'Hello World !'" 출력 : 큰따옴포 안에 작은 따옴표가 있음

- 출력에 차이가 있음 : repr는 객채형태 그대로 출력이 된다.

import datetime

a = datetime.datetime(2022, 1, 1)

str(a)                   # '2022-01-01 00:00:00' 출력
repr(a)                  # 'datetime.datetime(2022, 1, 1, 0, 0)' 출력

- repr는 객채형태 그대로 출력이 된다.

 

  • 문자열을 객체로 변환할 때 : eval()
a = "Hello World !"
b = str(a)
eval(b)                # 에러발생함

a = "Hello World !"
b = repr(a)
eval(b)                 # 에러발생하지 않음 : 'Hello World !' 출력

- 사용자가 보기 쉬운 형태는 시스템이 이해하는 형식은 아니다 : 변환을 할 수가 없다.

외부 라이브러리 다루기 - pip
  • 방법 1. Pycharm 패키지 매니저 사용

  • 방법 2. pip 사용
        - 설치 : pip install 패키지명
        - 삭제 : pip uninstall 패키지명
        - 특정 버전으로 설치 : pip install 패키지명==버전
        - 패키지 버전 업그레이드 : pip install --upgrade 패키지명
        - 설치된 패키지 확인 : pip list
        - 패키지 리스트 파일로 저장 : pip list --format=freeze > requirements.txt
        - 패키지 리스트 설치 : pip install -r requirements.txt)