dukim's blog

[WK01-Day 001][21.08.02.Mon.] Boostcamp 첫 시작 본문

Boostcamp AI Tech 2th

[WK01-Day 001][21.08.02.Mon.] Boostcamp 첫 시작

eliza.dukim 2021. 8. 6. 12:38

Intro

  • Pre-course 내용 중 평소 취약한 개념이었던 Python OOP 수강,
    취약 내용만을 선별적으로 정리
  • 과제 1, 2, 3 수행

강의 복습 내용

객체 지향 프로그래밍 개요

  • 객체 : 실생활에서 일종의 물건
    • 속성(Attribute)와 행동(Action)을 가짐
  • OOP는 이러한 객체 개념을 프로그램으로 표현
    • 속성은 변수 행동은 함수로 표현
  • Python은 OOP 언어
  • class : 설계도
  • instance : 구현체

Attribute 추가하기

  • __init__ : 객체 초기화 예약 함수
  • self : 생성된 인스턴스 자기 자신을 가리키는 변수

[참고] __의 의미

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

OOP Chracteristics *

  • 객체 지향 언어는 실제 세상을 모델링하기 위해 다음 세 가지 특징을 가진다.
  1. Inheritance(상속)
    • 부모 클래스의 속성과 메서드를 물려받은 자식 클래스 생성
    • super(): 부모 클래스를 지칭
      • init을 이용한 속성 값 초기화 때 부모 클래스가 가지고 있는 속성을 이용하거나
      • 새로운 메서드에서 부모 클래스의 메서드의 실행을 포함시키고자 할 때 사용 가능
        >>> myPerson = Person("Daeho", 34, "Male")
        >>> myPerson.about_me()
        저의 이름은 Daeho입니다. 나이는 34입니다.
        
        >>> myEmployee = Employee("Daeho", 34, "Male", 3000000, '2012/03/02')
        >>> myEmployee.about_me()
        저의 이름은 Daeho입니다. 나이는 34입니다.
        제 급여는 3000000원 이구요, 제 입사일은 2012/03/02입니다.
      • class Person(object): def __init__(self, name, age, gender): self.name = name self.age = age self.gender = gender def __str__(self): return f"제 이름은 {self.name}입니다. 나이는 {self.age}입니다." def about_me(self): print(f"제 이름은 {self.name}입니다. 나이는 {self.age}입니다.") class Employee(Person): # 부모 클래스 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_work(self): print("개미는 뚠뚠") def about_me(self): # override super().about_me() # 부모 클래스 함수 사용 print(f'제 급여는 {self.salary}원 이구요, 제 입사일은 {self.hire_date}입니다.')
  2. Polymorphism(다형성)
    • 추상 클래스(Abstract Class)와 관련된 개념
    • 예를 들어 도형(원, 삼각형, 사각형 등)에 대한 클래스를 만든다 할 때
      그 클래스의 메서드로 도형의 넓이를 계산 기능을 넣는다하자
    • 이때 아래 예시처럼 일반적인 도형에 대한 클래스를 만들어 놓고,
      넓이 계산 메서드는 비워두어 각 도형 클래스에서 이를 상속받아 넓이 계산 메서드를 작성하도록 할 수 있다.
    • [쉽게 말하면] 개념적으론 같은 기능을 하되 내부 로직을 다르게 구현하는 것을 Polymorphism이라 한다.
    • from abc import * class Shape(metaclass=ABCMeta): @abstractmethod def __init__(self, name): self.name = name @abstractmethod def area(self): pass # 위 코드를 아래와 같이 작성해도 동일하다 # ref : https://stackoverflow.com/questions/33335005/is-there-any-difference-between-using-abc-vs-abcmeta class Shape(ABC): @abstractmethod def __init__(self, name): self.name = name @abstractmethod def area(self): pass
    • 추상클래스 그 자체로는 인스턴스 생성 불가
    • 추상클래스를 상속받아 각 도형에 대한 클래스를 작성하면
    • class Circle(Shape): def __init__(self, name, radius): super().__init__(name) self.r = radius def area(self): return (self.r ** 2) * 3.1416 class Square(Shape): def __init__(self, name, width, height): super().__init__(name) self.w = width self.h = height def area(self): return self.w * self.h
  3. Visiblity(가시성)
  • 객체의 정보를 볼 수 있는 레벨을 조절하는 것
  • Encapsulation(캡슐화) 또는 Inromation Hiding(정보 은닉)
  • Class 설계시, 클래스 간 간섭/정보 공유를 최소화
  • 다른 클래스와 연동에 불필요한 내부 속성값이나 메서드는 숨김
  • 사용하는 상황
  • 가시성에 대한 고려 없이 작성한 경우
    가시성에 대한 고려 X
  • class Product(object): pass class InventoryVisible(object): def __init__(self): self.items = [] # Private variable, 타객체가 접근 불가 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)
  • 가시성을 고려하여 타객체의 접근을 막은 경우
    가시성을 고려하여 타객체의 접근을 막은 경우
  • 가시성을 고려하여 타객체의 접근을 막은 경우2
  • class InventoryInVisible(object): def __init__(self): self.__items = [] # Private variable, 타객체가 접근 불가 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)
  • 수정 불가하게 보호는 하되 접근은 허용해야하는 경우
    수정 불가하게 보호는 하되 접근은 허용해야하는 경우
  • from copy import deepcopy class InventoryInVisible(object): def __init__(self): self.__items = [] # Private variable, 타객체가 접근 불가 # property 자체는 함수를 속성값의 변수명처럼 쓸 수 있게함 @property # property decoratzor: 숨겨진 변수를 반환가능하z게 함 def items(self): return deepcopy(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)

ETC. Decorator

  • Prerequisites 1: First-class Object
    • 일급 객체 또는 일등함수로, 변수나 데이터 구조에 할당할 수 있는 객체
    • 파라메터로 전달이 가능하거나 리턴 값으로 사용될 수 있는 객체
    • 파이썬의 모든 함수는 일급 함수로, 파라메터로 전달 가능하고, 리턴값이 될 수 있다.
  • ex) 함수를 변수에 할당
  • def cube(x): return x ** 3 f = cube f(3)
  • ex) 함수를 파라메터로 사용
  • def cube(x): return x ** 3 def square(x): return x ** 2 def formula(method, arg_list): return [method(v) for v in arg_list]
  • Prerequisites 2: 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 greet_printer = print_msg("Hello, Python") greet_printer()
  • colsures의 활용: HTML Tag function
    • 같은 용도이지만 조금씩 다르게 변형된 함수를 만들 때 유용
    • def tag_fnc(tag, text): text = text tag = tag def inner_fnc(): return f'<{tag}>{text}<{tag}>' return inner_fnc h1_fnc = tag_fnc("title", 'Hello, Guys') p_fnc = tag_fnc("p", 'Notice')
  • decorator function: closure function을 더 간단하게 만들어 줌
    • 데코레이터 정의 함수는 입력을 함수로 받음
    • 내부에 있는 args, kwargs는 데코레이터로 감싸는 함수의 인자
      image
    • def line(f): def inner(*args, **kwargs): print("-" * 50) f(*args, **kwargs) print("-" * 50) return inner @line def printer(msg): print(msg) printer("Hello")
    • 여러개의 decorator를 중첩시키는 것도 가능(예시 생략)
    • decorator에 인자를 넣어 줄 수 있다. 이 때는 데코레이터 정의 함수를 한 겹 더 감싸 인자를 입력 받는다.
      image
    • # 데코레이터 자체에도 argument 입력 가능 # 이떄는 def multiply_k(k): def wrapper(f): def inner(*args): result = f(*args) return k * result return inner return wrapper @multiply_k(3) def sum_two(n): return n + 2

과제 수행 과정 / 결과물

  • 필수 과제 1 - 3 수행
  • 과제 1은 무난하게 완료
  • 과제 2, 3에서 기본 python 문자열 처리 방식을 쓰기보다 최대한 정규표현식 사용했으며 기억해두면 좋을 팁 몇 가지 정리
  • 2칸 이상의 띄어쓰기를 모두 한 칸으로 변환하기
  • input_string = re.sub(r'\s+', ' ', input_string)
  • 앞뒤 필요없는 띄어쓰기 제거(strip 메서드의 정규표현식)
  • normalized_string = re.sub(r'(^\s+)|(\s+$)', '', input_string)
  • underscore variable을 을 camelcase variable로 변환하는 코드
    • 앞 뒤 underscore 무시
    • underscore로만 이루어진 문자열은 빈 문자열 반환
    • def to_camel_case(underscore_str): # 아래 패턴은 언더스코어를 제외한 연속된 문자열(알파벳, 구두점(.), 하이픈(-), 숫자, 공백)을 매칭 underscore_pattern = re.compile(r'[a-zA-Z.\-\d\s]+[^_]') pattern_group = underscore_pattern.findall(underscore_str) if len(pattern_group) > 1: camelcase_str = pattern_group[0].lower() + \ ''.join( list(map(lambda x : x.lower().capitalize(), pattern_group[1:])) ) elif len(pattern_group) == 1: camelcase_str = pattern_group[0] else: camelcase_str = '' return camelcase_str

피어세션

  • 자기소개
  • 그라운드 룰 정함
    • 전주차 학습 내용 공유
    • 모더레이터는 돌아가면서
    • 지각시 스벅 기프티콘 돌리기
  • 오늘 학습했던 Python OOP 학습 내용 공유

학습 회고

  • Python OOP에서 매번 헷갈렸던 부분인 아래 세 가지를 명확히함
    • super()
    • visibility의 개념과 코드 적용
    • decorator
  • 정규표현식이 너무 헷갈린다. 정리할 필요가 있다.
Comments