Python/[코칭스터디 9기] 인공지능 AI 기초 다지기

[인공지능(AI) 기초 다지기] 2. 파이썬 다지기 (1)

김초송 2023. 1. 26. 19:19

https://www.boostcourse.org/ai100/joinLectures/233686

 

4. 파이썬 기초 문법 3

- Object Oriented Programming (OOP, 객체 지향 프로그래밍)

  • 만들어 놓은 코드를 재사용
  • 주체, 행동, 데이터들을 중심으로 프로그램 작성 후 연결
  • 객체는 실생활에서 일종의 물건
  • 객체는 속성(Attribute)와 행동(Action)을 가짐
  • 속성 = 변수(Variable) / 행동 = 함수(Method)
  • OOP는 설계도에 해당
  • OOP는 클래스(Class, 붕어빵틀).와 실제 구현체인 인스턴스(Instance, 붕어빵)으로 나눔

 

- Class / Object

# class 선언
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. My back number is %d." %(self.name, self.back_number)
    
    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
        
jinhyun = SoccerPlayer("Jinhyun", "MF", 10)
  • class : 예약어
  • SoccerPlayer : class 이름 <- PascalCase
  • object : 상속받는 객체명 (안 쓰면 object 자동 상속)
  • Atrribute 추가하기 
    __init__, self
    __init__은 객체 초기화 예약 함수
  • __는 특수한 예약 함수나 변수, 함수명 변경(맨글링)으로 사용 
    __main__, __add__, __str__(print(object) 할 때 나오는 내용), __eq__
  • Method 구현하기
    method(Action) 추가는 기존 함수와 같으나, 반드시 self를 추가해야 class 함수로 인정됨
  • self = 생성된 인스턴스 자기자신
  • Object(Instance) 사용하기
    Object 이름 선언과 함께 초기값 입력하기
  • jinhyun : 객체명
  • SoccerPlayer("Jinhyun", "MF", 10) : 클래스명(__init__ 함수 interface, 초기값)

 

- Inheritance (상속)

  • 부모클래스로부터 속성과 method를 물려받은 자식 클래스를 생성하는 것
class Person:
    def __init__(self, name, age, gender):
        self.name = name
        self.age = age
        
    def about_me(self):
        print("저의 이름은 ", self.name, "입니다. 나이는 ", self.age, "살 입니다")
        
class Employee(Person):
    def __init__(self, name, age, gender, salary, hire_date):
        super().__init__(name, age, gender) # 부모 객체 사용
        self.salary = salary
        self.hire_date = hire_date
        
    def do_word(self):
        print("열심히 일 합니다.")
    
    def about_me(self): # 부모 클래스 함수 재정의
        super().about_me() # 부모 클래스 함수 사용
        print("급여는 ", salary, "입니다.")
  • class 자식 클래스(부모 클래스):
  • super() : 자기 자신의 부모 클래스

 

- Polymorphism (다형성)

  • 같은 이름 메소드의 내부 로직을 다르게 작성
  • Dynamic Typinc 특성으로 인해 파이썬에서는 같은 부모클래스의 상속에서 주로 발생
  • 부모 클래스와 형제 클래스가 함수명은 같지만 구현 내용은 다름 (다른 역할)
  • 함수 재정의
class Animal:
    def __init__(self, name):
        self.name = name
    
    def talk(self):
        raise NotImplementedError("Subclass must implement abstract method") # defined by convention only
        
class Cat(Animal):
    def talk(self):
        return 'Meow'
  • NotImplementedError : 자식 클래스가 반드시 함수 구현

 

- Visibility (가시성)

  • 객체의 정보를 볼 수 있는 레벨을 조절하는 것
  • 누구나 객체 안에 모든 변수를 볼 필요가 없음
    1. 객체를 사용하는 사용자가 임의로 정보 수정
    2. 필요 없는 정보에는 접근할 필요 없음
class Product(object):
    pass

class Inventory(object):
    def __init__(self):
        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)
  • Product 객체를 Inventory 객체에 추가
  • Inventory에는 오직 Product 객체만 들어감
  • Inventory에 Product가 몇 개인지 확인이 필요
  • Inventory에 Product items는 직접 접근 불가
  • __items : Private 변수로 선언 -> 타객체(외부)가 접근 못함
class Inventory(object):
    def __init__(self):
        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)

    @property
    def items(self):
        return self.__items # copy 
        
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
items.append(Product())
print(my_inventory.get_number_of_items())
  • Inventory에 Product items 접근 허용
  • @property : property decorator 숨겨진 변수를 반환하게 해줌
  • items = my_inventory.items : Property decorator로 함수를 변수처럼 호출
  • decorator : 함수명을 변수명처럼 쓸 수 있게 해줌

 

- Encapsulation

  • 캡슐화 또는 정보 은닉 (Information Hiding)
  • 클래스를 설계할 때, 클래스 간 간섭/정보 공유의 최소화
  • 서로 정보 접근은 최소화하면서 인터페이스만 알면 쉽게 쓸 수 있게 함

- First-class Object 

  • 일급 함수 또는 일급 객체
  • 변수나 데이터 구조에 할당이 가능한 객체
  • parameter로 전달 가능 + 리턴 값으로 사용
  • 함수 자체를 파라메터나 리턴 값으로 사용함 ex) map(f, ex)
  • 실제로는 메모리 주소가 연결됨
  • 파이썬 함수는 일급 함수
def square(x):
    return x*x

def cube(x):
    return x*x*x

def formula(method, argument_list):
    return [method(value) for value in argument_list]
  • def formula(method : 함수를 parameter로 사용

 

- Inner Function

  • 함수 내에 또다른 함수가 존재
def print_msg(msg):
    def printer():
        print(msg)
    printer()
    
print_msg("Hello, Python")

# closures
def print_msg(msg):
    def printer():
        print(msg)
    retunr printer
    
another = print_msg("Hello, Python")
another()
  • Hello, Python 이 msg = 인자가 됨
  • closures : inner function을 return값으로 반환
    같은 목적의 다양한 변형이 되는 함수들을 만들어 낼 수 있음

 

- Decorator

  • 복잡한 closure 함수를 간단하게
def star(func):
    def inner(*args, **kwargs):
        print(args[1] * 30)
        func(*args, **kwargs)
        print(args[1] * 30)

    return inner

@star
def printer(msg, mark):
    print(msg)

printer("Hello", "*")
def generate_power(exponent):
    def wrapper(f):
        def inner(*args):
            result = f(*args)
            return exponent ** result
        return inner
    return wrapper

@generate_power(2)
def raise_two(n):
    return n ** 2
  • exponent = 2
  • f = raise_two
  • *args = n -> f가 쓰는  모든 argument들을 가져옴
  • f(*args) = raise_two(n)
  • 결과값: 2^(7^2)