Upstage AI LAB 부트캠프 5기/실시간 공부내용 복습

[2024.10.04] 파이썬 프로그래밍 이해하기

김 도경 2024. 10. 4. 16:59

* 강의를 듣고 필기한 내용일 이후에 따로 정리한 내용입니다.

* https://glowdp.tistory.com/16 에서 이어지는 게시물 입니다.

 

Class

- 여기까지가 파이썬의 기초

- 파이썬은 OOP 패러다임으로 구현된 언어

    - OOP : Object-Oriented Programming , 객체 지향 프로그래밍   -> 다른 언어들의 단점을 없애고 나온 언어
          - assembly language
          - C language : 하드웨어 제어와 사용자의 편리함을 위하여, 나온 언어

          - data + (related)function 

    - 추상화 = 개념화, 현실세계에 존재하는 것을 어떻게 걔념으로 만들거냐가 중요한 것.

           - 인간관계를 걔념화 하면? -> 사람마다 다른 방식으로 구현 : 시각화

    - object -- (abstraction) --> class

    - Data Structure(자료구조)

#class의 기본적인 구조

class 생성자_이름
	def __init__(self, 변수1, 변수2, 변수3, 변수4, ...)
    	self.변수1 = 변수1
        self.변수2 = 변수2
        self.변수3 = 변수3
        self.변수4 = 변수4)
class Notebook:
    def __init__(self,               # init이라는 함수 안에 원하는 변수를 적음
                 manufacturer: str,
                 color: str,
                 kg: float,
                 mem: int,
                 ssd: int) -> None:
        self.manufacturer = manufacturer
        self.color = color
        self.kg = kg
        self.mem = mem
        self.ssd = ssd
        
# 클래스의 생성자(constructor)를 불러와봅니다.

nb = Notebook('Apple', 'silver', 1.8, 32, 512)         #constructor call
#<=> Notebook.__init__(), self = nb (self에 들어갈 parameter는  안 넣어줘도 됨)
#<=> Notebook.__init__(nb, ...)
nb2 = Notebook('Samsung', 'blue' , 1.6, 16, 256)
#<=> Notebook.__init__(nb2, ...)

- notebook이라는 클래스를 정의 : notebook이라는 사물(개념)이 가지는 실체적인 특징들을 찾아서, 변수를 정의해야함

- 정의된 변수를 실제로 만들어주는 함수를 생성자(constructor)라고 함.

- 생성자를 정의하는 함수는 __init__()

 - none을 붙이는 이유 : 타입 힌트를 제공하기 위함 : 객체를 초기화하는 생성자(constructor)로, 반환값이 없다는 것을 명시적으로 나타내기 위해 None을 사용

nb.manufacturer, nb2.manufacturer
('Apple', 'Samsung')

 

- Notebook이라는 개념을 클래스로 구현.
- Notebook에서 필요한 여러가지 기능을 함수(class method)로 구현.

  • 클래스 내부의 함수를 구현
# 클래스 내부의 함수를 구현합니다.
# 해당 노트북의 운영체제가 UNIX 계열 운영체제인지 아닌지 확인하는 Class Method를 구현합니다.
## 윈도우 계열 vs 나머지(UNIX)

class Notebook:
    def __init__(self, manufacturer, model, ram_size, ssd_size, os):
        self.manufacturer = manufacturer
        self.model = model
        self.ram_size = ram_size
        self.ssd_size = ssd_size
        self.os = os

    ## TO-DO ##
    def is_UNIX(self) -> bool:
        if self.os == 'windows':
            return False
        elif self.os in ['macos', 'linux']:  # 'in'은 == 없이 사용
            return True
        else:
            return False  # 기타 OS에 대한 처리

# 해당 노트북의 운영체제가 UNIX 계열 운영체제인지 아닌지 확인하는 Class Method를 구현합니다.
## 윈도우 계열 vs 나머지(UNIX)

- self는 그냥 문법! 외워야한다.

# 해당 노트북의 모델을 출력해주는 Class Method를 구현합니다.
# 클래스의 생성자(countructor)을 불러와봅니다.

# Notebook 클래스 인스턴스 생성
galaxybook = Notebook('Samsung', '4 ultra', 64, 2048, 'windows')
macbook = Notebook('Apple', 'm3 max', 192, 4096, 'macos')

# is_UNIX 메서드 호출
print(galaxybook.is_UNIX())  # False
print(macbook.is_UNIX())     # True
  • 클래스 상속 (Class inheritence)
    - Notebook들은 제조사마다 다른 모델이 있음
    - 해당 모델들은 Notebook이지만, 모델마다 다른 특징을 가짐.
    - 노트북의 개념을 그대로 이어받아, 모델마다 다른 개념을 Class로 구현.
    - 하위클래스에서 어떤 method를 호출하면, 해당 클래스에서 정의를 찾고 없다면 상위클래스에 정의가 되어있는지 확인해서 사용

- 모듈 클래스에 대한 설명 : https://pytorch.org/docs/stable/_modules/torch/nn/modules/module.html#Module

# notebook class를 상속받아서 새로운 MacBook class를 정의
## Notebook(superclass) -> MacBook(subclass)
class MacBook(Notebook):     #클래스 이름을 소괄호안에 넣으면 상속이 됨
    def __init__(self, 
                 manufacturer: str, 
                 model: str, 
                 ram_size: int, 
                 ssd_size: int, 
                 os: str, 
                 display_size: int):
        super().__init__(manufacturer, model, ram_size, ssd_size, os)
        self.display_size = display_size                 #Notebook의 subclass인 Macbook클라스에서 새롭게 정의한 변수.
        
class GalaxyBook(Notebook):
    def __init__(self, 
                 manufacturer: str, 
                 model: str, 
                 ram_size: int, 
                 ssd_size: int, 
                 os: str, 
                 lineup: str,   # lineup 추가
                 display_size: int):
        super().__init__(manufacturer, model, ram_size, ssd_size, os)
        self.lineup = lineup               #notebook의 subclass인 galaxybook에서 새롭게 정의한 변수
        self.display_size = display_size  # display_size 추가
# notebook class를 상속받아서 새로운 Dell_Laptop class를 정의
mb = MacBook('apple', 'MacBook M3 Max', 128, 4096, 'macOS', 14)
gb = GalaxyBook('samsung', '4', 32, 1024, 'windows', 'Pro', 15)  # display_size 추가

mb.display_size, gb.lineup

 

-에러를 발생시켜서, 강제로 코드를 멈출때 사용하는 코드 : else: return Expection

    ## TO-DO ##
    def is_UNIX(self) -> bool:
        if self.os == 'windows':
            return False
        elif self.os in ['macos', 'linux']:  # 'in'은 == 없이 사용
            return True
        else:         #강제로 에러 발생시키기 가능->강제로 코드를 멈추고 싶을때 
            return Expection("windows, macos, linux중에 하나를 입력해주세요")  # 기타 OS에 대한 처리

 

  • Method Overriding
# 각 모델마다 다르게 정보를 출력해주는 is_UNIX 함수를 재정의합니다.
class MacBook(Notebook):
    # super(Notebook).__init__()  # 상위클래스에 있는 init을 그대로 사용하겠다.
    def __init__(self, manufacturer, model, ram_size, ssd_size, os, display_size):
        # 상위클래스의 생성자에서 사용하는것도 쓰고,
        super().__init__(manufacturer, model, ram_size, ssd_size, os)
        # 추가로 변수들을 더 할당해서 쓰겠다.
        self.display_size = display_size   # 14 / 16

    # Method Overriding은 하위 클래스에서 상위 클래스의 class method를 재정의하는 것.
    def is_UNIX(self) -> bool:
        if self.os == "windows":
            return False
        elif self.os in ['high sierra', 'catelina', 'mohave']:
            return True
mb2 = MacBook('apple', 'MacBook M3 Max', 128, 4096, 'macOS', 14)

mb2.is_UNIX    # class method object
mb2.is_UNIX()  # class method call

 

PyTorch를 사용할 때 알아야할 걔념

  • decorator
    - 함수나 메서드의 동작을 변경하거나 확장하는 기능을 제공하는 함수
    - 주로 로그, 권한 확인 등의 추가 작업을 쉽게 구현하는 데 사용
  • generator
    - 데이터를 한 번에 모두 메모리에 올리지 않고, 필요한 순간에 값을 생성하는 함수
    - yield 키워드를 사용하여 값 반환.
  • iterator
    - 반복 가능한 객체로부터 데이터를 하나씩 순차적으로 꺼내는 객체
    - __iter__()와 __next__() 메서드를 사용
  • DataLoader
    - PyTorch에서 데이터를 쉽게 로드하고, 배치 단위로 모델에 전달하기 위해 사용되는 유틸리티
  • OOM(Out-of-Memory)
    - 컴퓨터 시스템에서 메모리 부족으로 인해 발생하는 에러
    - 딥러닝 모델을 훈련하거나 대규모 데이터를 처리할 때 메모리가 부족해 프로그램이 중단될 때 발생
    - GPU나 CPU의 메모리 용량보다 큰 데이터를 한꺼번에 처리하려 할 때 발생
    - 이를 해결하기 위해서는 배치 크기 조정, 모델 경량화, 메모리 최적화 등의 방법
문제 풀어보기

1. 음식 주문 시스템 만들기

- 메뉴 클래스(Menu), 주문 클래스(Order), 그리고 주문 관리 클래스(OrderManager)를 구현
    - Menu 클래스: 음식 이름과 가격을 관리합니다.
    -  Order 클래스: 특정 메뉴 항목에 대한 주문을 담습니다. 주문 번호와 주문한 메뉴 항목의 리스트를 포함합니다.
    -  OrderManager 클래스: 모든 주문을 관리합니다. 새 주문을 추가하고, 모든 주문을 보여주는 기능을 가집니다.

### 1. Menu 클래스

class Menu:
    # constructor(생성자)
    ## 클래스를 구현할 때 무조건 생성자를 만들고, 입력받은 모든 parameter는 self.~~ = ~~로 모두 저장한다.
    def __init__(self, name: str, price: int):
        self.name = name
        self.price = price

### 2. Order 클래스
class Order:
    # self에 저장한건 객체 내부에서는 어디서든 self라는 변수를 통해서 접근이 가능하다.
    def __init__(self, order_id):
        self.order_id = order_id
        self.menus = []  # Order 생성자에서 새롭게 생성. parameter passing을 받을 필요는 없음.

    def add_item(self, menu: Menu) -> None:
        self.menus.append(menu)

        
### 3. OrderManager 클래스
class OrderManager:
    def __init__(self):
        self.orders = []
        self.order_id = 1
    
    def add_new_order(self) -> Order:
        order = Order(self.order_id)
        self.orders.append(order)   # 생성한 order를 저장
        self.order_id = self.order_id + 1
        return order

    def show_all_orders(self):
        for order in self.orders:
            print(f"Order ID: {order.order_id}")
            print("Items Ordered:")
            
            for menu in order.menus:
                print(f"{menu.name}: ${menu.price}")
            print()


### 사용 예
# 메뉴 항목 생성
pizza = Menu("Pizza", 10)
pasta = Menu("Pasta", 8)
salad = Menu("Salad", 5)

# 주문 관리자 생성
order_manager = OrderManager()

# 새 주문 생성
order1 = order_manager.add_new_order()     #새로운 order를 생성
order1.add_item(pizza)                     # 그 order에 주문한 메뉴를 추가
order1.add_item(salad)

# 또 다른 주문 생성
order2 = order_manager.add_new_order()
order2.add_item(pasta)

# 모든 주문 보기
order_manager.show_all_orders()      # 이 때까지 만들어낸 모든 order를 호출
아래는 show_all_orders 실행결과
Order ID: 1
Items Ordered:
Pizza: $10
Salad: $5

Order ID: 2
Items Ordered:
Pasta: $8

 

Visual Stuido Code를 이용하여, .py로 바꾸는 방법

 

python 개발용 VSCode extentions

  1. Python
  2. Jupyter
  3. Code Runner
  4. Pylance

 

.py -> python script file
.ipynb -> interactive python notebook file

terminal : 출력되는 창

CLI(Command Line Interface)  : 명령줄 인터페이스 또는 명령어 인터페이스라고 불리는 방식

                          - 사용자가 명령어를 직접 입력하여 컴퓨터와 상호작용하는 인터페이스

                          - 마우스와 클릭을 사용하는 대신, 텍스트 기반 명령어를 입력하여 컴퓨터의 프로그램이나 기능을 실행

GUI(Graphic User Interface) : 그래픽 사용자 인터페이스

                          - 사용자가 아이콘, 버튼, 메뉴, 창 같은 그래픽 요소를 사용해 컴퓨터와 상호작용하는 방식의 인터페이스

                          - 마우스나 터치스크린을 이용해 직관적으로 클릭하거나 드래그하면서 컴퓨터 작업을 수행할 수 있도록 설계된 인터페이스

 

코드를 모듈 단위로 만들겠다 -> 서로 "독립적인" 코드로 나누어서 만들겠다

SW Architect(Software Architect) : 소프트웨어 시스템의 전반적인 구조설계를 책임지는 전문가
- 개발 과정에서 시스템의 기본적인 틀을 만들고, 구조적인 설계기술적 결정을 주도하여 소프트웨어가 효율적이고 확장 가능하며 안정적으로 동작

코드의 유지보수 : 이건 필수

 

3개의 클래스를 각각의 코드로 나누기

3개의 py를 만든다.

 

- 코드를 나눈다.

 

encapsulation : 은닉화, 캡슐화

- 객체지향 프로그래밍(OOP)에서 중요한 개념 중 하나

- 데이터(속성)와 메서드(기능)를 하나의 단위로 묶고, 외부에서 직접 접근할 수 없도록 제한하는 것을 의미

- 이를 통해 클래스의 내부 상태를 보호하고, 객체가 의도한 방식으로만 상호작용할 수 있게 한다.

 

메뉴에 있는 것을 편하게 가져올 수 있다.

 

 


  • class 복습은 필수! : 추가 문제 꼭 풀어보기