본문 바로가기
네이버 부스트캠프 AI Tech/Pre-course

2. Python Object-Oriented Programming

by 중앙백 2021. 12. 3.

1. 클래스와 객체 - 객체 지향 언어의 이해

 

프로그램을 작성할 때 1) 시작부터 끝까지 순서대로 작성. 2) 주체들의 행동과 데이터들을 중심으로 작성 후 연결. 하는 두 가지 방식이 있는데 2)를 객체 지향 프로그램이라고 한다.

 - Object-Oriented Programming, OOP

 - 객체 : 실생활에서 일종의 물건. 속성(Attribute)와 행동(Action)을 가짐.

 - OOP는 이러한 객체 개념을 프로그램으로 표현. 속성은 변수(variable), 행동은 함수(function)으로 표현됨.

 - 파이썬 역시 객체 지향 프로그램 언어.

 

(예) 인공지능 프로그램을 작성할 때,

객체 종류 : 팀, 선수, 심판, 공

Action : 선수 - 공을 차다, 패스하다

           심판 - 휘슬을 불다, 경고를 주다

Attribute : 선수 - 선수 이름, 포지션, 소속팀

              팀 - 팀 이름, 팀 연고지, 팀소속 선수

 

OOP는 설계도에 해당하는 클래스(class)와 실제 구현체인 인스턴스(instance)로 나뉨.

(예) 붕어빵틀(클래스)와 붕어빵(인스턴스) -> 다양한 붕어빵 가능. 팥, 슈크림, 말차 등등

 

 

 

2. Python coding해보며 알아보자

 

 (1) class 선언하기

class SoccerPlayer(object):

class예약어 : class이름 : 상속받는 객체명(object는 python3에서는 자동 상속)

 

(참고) python naming rule

  변수와 Class명 함수명은 짓는 방식이 존재.

   - snake_case : 띄어쓰기 부분에 "_"를 추가. 뱀처럼 늘여쓰기, 파이썬 함수/변수명에 사용

   - CamelCase : 띄어쓰기 부분에 대문자. 낙타의 등 모양, 파이썬 Class명에 사용

 

 

(2) Attribute 추가하기

class SoccerPlayer(object):
    def __init__(self, name: str, position: str, back_number: int):
        self.name = name
        self.position = position
        self.back_number = back_number


abc = SoccerPlayer("son", "FW", 7)
jinhyun = SoccerPlayer("Jinhyun", "MF", 10)

 - Attribute 추가는 __init__ , self와 함께!
   __init__은 객체 초기화 예약 함수

 

(3) method 구현하기

class SoccerPlayer(object):
    def __init__(self, name: str, position: str, back_number: int):
        self.name = name
        self.position = position
        self.back_number = back_number

    def __str__(self):
        return "Hello, My name is %s. I play in %s in center" % \
               (self.name, self.position)

    def __add__(self, other):
        return self.name + other.name
        
    def change_back_number(self, new_number):
        print("선수의 등번호를 변경합니다 : From %d to %d" % \
        (self.back_number, new_number))
        self.back_number = new_number


abc = SoccerPlayer("son", "FW", 7)
jinhyun = SoccerPlayer("Jinhyun", "MF", 10)
print(abc is jinhyun)  # 둘은 다른 객체
print(jinhyun)
print(abc + jinhyun)

 

(참고) 파이썬에서 __의 의미(언더바 2개)

 : 특수한 예약 함수나 변수 그리고 함수명 변경(맨글링)으로 사용

   (예) __main__ , __add__ , __str__ : print함수에 출력 , __eq__

 

 

(4) objects(instance) 사용하기

jinhyun = SoccerPlayer("Jinhyun", "MF", 10)
 객체명     Class명   _init_함수 interface, 초기값

* self란? 생성된 instance. 외부에선 jinhyun이지만 코드 안에서는 self라고 불림.

 

 

 

3. OOP Implementation Example

 

(1) 구현 가능한 OOP 만들기 - 노트북

 - Note를 정리하는 프로그램

 - 사용자는 Note에 뭔가를 적을 수 있다.

 - Note에는 Content가 있고 내용을 제거 가능

 - 두 개의 노트북을 합쳐 하나로 만들 수 있다.

 - Note는 Notebook에 삽입된다.

 - Notebook은 Note가 삽입될 때 페이지를 생성하며, 최고 300페이지까지 저장 가능

 - 300 페이지가 넘으면 더 이상 노트를 삽입하지 못한다.

 

* class scheme

  Notebook Note
method add_note write_content
remove_note remove_all
get_number_of_pages  
variable title content
page_number  
notes  

 

 Note class

class Note(object):
    def __init__(self, content = None):
        self.content = content
        
    def write_content(self, content):
        self.content = content
        
    def remove_all(self):
        self.content = ""
        
    def __add__(self, other):
        return self.content + other.content
    
    def __str__(self):
        return self.content

 

NoteBook class

class NoteBook(object):
    def __init__(self, title):
        self.title = title
        self.page_number = 1
        self.notes = {}
        
    def add_note(self, note, page = 0):
        if self.page_number < 300:
            if page == 0:
                self.notes[self.page_number] = note
                self.page_number += 1
            else:
                self.notes = {page : note}
                self.page_number += 1
        else:
            print("Page가 모두 채워졌습니다.")
            
    def remove_note(self, page_number):
        if page_number in self.notes.keys():
            return self.notes.pop(page_number)
        else:
            print("해당 페이지는 존재하지 않습니다.")
        
    def get_number_of pages(self):
        return len(self.notes.keys())

 

 

4. OOP characteristics

 

객체 언어의 특징 : 실제 세상을 모델링

3 속성 : Inheritance(상속) Polymorphism(다형성) Visibility(가시성)

 

(1) Inheritance

 - 부모클래스로부터 속성과 Method를 물려받은 자식 클래스를 생성 하는 것

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
        
        
class Korean(Person):
    def __init__(self, name, age, gender):
        super().__init__(name, age)  # 부모 객체 사용
        self.gender = gender
     
     
first_korean = Korean("Sungchul", 35, "M")
print(first_korean.name)

 

(2) Polymorphism 다형성

 - 같은 이름 메소드의 내부 로직을 다르게 작성

 - Dynamic Typing 특성으로 인해 파이썬에서는 같은 부모클래스의 상속에서 주로 발생함

 - 중요한 OOP의 개념 그러나 너무 깊이 알 필요 X

class Animal:
    def __init__(self, name):
        self.name = name
    
    def talk(self):  # Abstract method, defined by convention only
        raise NotImplementedError("Subclass must implement abstract method")


class Cat(Animal):
    def talk(self):
        return "Meow!"
        
class Dog(Animal):
    def talk(self):
        return "Woof! Woof!"
        

animals = [Cat("missy"), Cat('Mr.dog'), Dog("Lassie")]

for animal in animals:
    print(animal.name + ': ' + animal.talk())

 

(3) Visibility 가시성

 - 객체의 정보를 볼 수 있는 레벨을 조절하는 것

 - 누구나 객체 안에 모든 변수를 볼 필요가 없음

    1) 객체를 사용하는 사용자가 임의로 정보 수정

    2) 필요없는 정보에는 접근 할 필요가 없음

    3) 만약 제품으로 판매한다면? 소스의 보호

 

(참고) Encapsulation

 - 캡슐화 또는 정보 은닉 (Information Hiding)

 - Class를 설계할 때, 클래스 간 간섭/정보공유의 최소화

 - 심판 클래스가 축구선수 클래스 가족 정보를 알아야 하나?

 - 캡슐을 던지듯, 인터페이스만 알아서 써야함

 

(예시 1)

 - Product 객체를 Inventory 객체에 추가

 - Inventory에는 오직 Product 객체만 들어감

 - Inventory에 Product가 몇 개인지 확인이 필요

 - Inventory에 Product items는 '직접 접근이 불가'

class Product(object):
    pass
    

class Inventory(object):
    def __init__(self):
        self.__items = []  # Private 변수로 선언 타객체가 접근 못함
        
    def add_new_item(self, product):
        if type(product) == Product:
            self.__items.append(product)
            print("new item added")
        else:
            raise ValueError("Invalid Item")
            
    def get_number_of_items(self):
        return len(self.__items)
my_inventory = Inventory()
my_inventory.add_new_item(Product())
my_inventory.add_new_item(Product())
print(my_inventory.get_number_of_items())

print(my_inventory.__items)
my_inventory.add_new_item(object)

(예시 2)

 - Product 객체를 Inventory 객체에 추가

 - Inventory에는 오직 Product 객체만 들어감

 - Inventory에 Product가 몇 개인지 확인이 필요

 - Inventory에 Product items '접근 허용'

class Product(object):
    pass
    

class Inventory(object):
    def __init__(self):
        self.__items = []  # Private 변수로 선언 타객체가 접근 못함
        
    @property   # property decorator 숨겨진 변수를 반환하게 해줌
    def items(self):
        return self.__items
        
    def add_new_item(self, product):
        if type(product) == Product:
            self.__items.append(product)
            print("new item added")
        else:
            raise ValueError("Invalid Item")
            
    def get_number_of_items(self):
        return len(self.__items)
my_inventory = Inventory()
my_inventory.add_new_item(Product())
my_inventory.add_new_item(Product())
print(my_inventory.get_number_of_items())

items = my_inventory.items  # Property decorator로 함수를 변수처럼 호출
items.append(Product())
print(my_inventory.get_number_of_items())

 

(5) decorate

 - First-class objects

    일등함수 또는 일급 객체

    변수나 데이터 구조에 할당이 가능한 객체

    파라메터로 전달이 가능 + 리턴 값으로 사용

    ** 파이썬의 함수는 일급함수

 

 - Inner function

    함수 내에 또 다른 함수가 존재

def print_msg(msg):
    def printer():
        print(msg)
    printer()
    
    
print_msg("Hello, Python")

    closures : inner function을 return값으로 반환

def print_msg(msg):
    def printer():
        print(msg)
    return printer
    
    
another = print_msg("Hello, Python")
another()
def tag_func(tag, text):
    text = text
    tag = tag
    
    def inner_func():
        return '<{0}>{1}<{0}>'.format(tag, text)
        
    return inner_func
    
h1_func = tag_func('title', "This is Python Class")
p_func = tag_func('p', "Data Academy")

 - Decorator

    복잡한 클로져 함수를 간단하게!

def star(func):
    def inner(*args, **kwargs):
        print("*" * 30)
        func(*args, **kwargs)
        print("*" * 30)
    return inner
    
@star
def printer(msg):
    print(msg)
printer("Hello")

 

 

 

 

 

 

* 출처 : 네이버 부스트코스 [부스트캠프 AI Tech 3기 Precourse]

 

 

 

'네이버 부스트캠프 AI Tech > Pre-course' 카테고리의 다른 글

5. Python Data Handling  (0) 2021.12.05
4. File / Exception / Log Handling  (0) 2021.12.05
3. Module and Project  (0) 2021.12.05
1. 딥러닝의 역사  (0) 2021.12.03
부스트캠프 AI Tech 3기 준비  (0) 2021.12.03

댓글