Object-Oriented Programming

클래스와 인스턴스

class Student(object):  # 클래스 선언부 (예약어 - 클래스 이름 - 부모 클래스)
    SCHOOL = 'GOORM'    # 클래스 속성 (Class attribute)

    def __init__(self, name: str, sid: int):     # 생성자 (현재 수정하고자 하는 객체=self)
        self.name = name                         # 속성 (Attribute)
        self.sid = sid
        self.classes = set()

    # 클래스 함수 (Method)
    def take_class(self, class_name: str) -> None:
        self.classes.add(class_name)

    def drop_class(self, class_name: str) -> None:
        self.classes.discard(class_name)

# 클래스 생성
gildong_hong = Student('Gildong Hong', 20224352)
# 속성 출력
printgildong_hong.name, "in", Student.SCHOOL)
# 메소드 실행
gildong_hong.take_class("CS101")
gildong_hong.take_class("CS202")
gildong_hong.drop_class("CS101")

# 출력 결과
# Gildong Hong in GOORM

 


 

Magic Method (매직 메소드)

(cf) __init__, __call__, ___length__, __getitem__ 을 많이 사용함

  생성자 (__init__)

  소멸자 (__del__)

  Indexing 메소드 (__getitem__, __setitem__)

  etc

#Indexing
class DoubleMapper(object):
    def __init__(self):
        self.mapping = {}
    def __getitem__(self, index):  # Indexing get
        return self.mapping.get(index, index * 2)
    def __setitem__(self, index, item):  # Indexing set
        self.mapping[index] = item
mapper = DoubleMapper()
print(mapper[10], mapper[1, 2]) # 20 (1, 2, 1, 2)
mapper[10] = 15
print(mapper[10], mapper[1, 2]) # 15 (1, 2, 1, 2)
#lengh 메소드
class Dataset:
	def __init__(self, data, times=3):
        self.data = data
        self.times = times
    def __len__(self):  # len(instance) 호출될 시 호출
        return len(self.data) * self.times
    def __getitem__(self, index):
        if index > len(self):
            raise IndexError()
        return self.data[index % len(self.data)]
dataset = Dataset([10, 2, 5, 2], times=5)
print(len(dataset)) # 20\
#Typing
class Student:
    def __init__(self, name: str, sid: int):
        self.name = name
        self.sid = sid
    def __str__(self): # str 형변환
        return self.name + '_' + str(self.sid)
gildong_hong = Student("Gildong Hong", 20224372)
print(gildong_hong)  # Gildong Hong_20224372
#함수화 메소드(__call__)
class AdditionNumber(object):
    def __init__(self, number: int):  # 생성자
        self.number = number

    # 함수화 메소드
    def __call__(self, number: int): # *args, **kargs도 받을 수 있다.
        return number + self.number

addition_5 = AdditionNumber(5)
print(addition_5(10))  # 15 ==> 객체를 함수처럼 사용
                       # (cf) add.__call__(*args)
# iterable
seq = [1, 2, 3, 4, 5]
for elem in seq:
    print(elem)
print()

seq = list([1, 2, 3, 4, 5])
iterable = iter(seq)    #iter 내장함수(__iter__호출)
while True:
    try:
        elem = next(iterable)   #next 내장함수(__next__호출)
    except StopIteration:
        break
#context manager
class Student:
    def __init__(self, name, sid):
        self.name = name
        self.sid = sid

    def __enter__(self):  # with 구문에 들어갈 때 사용, return 값이 as 이하로 할당
        self.classes = set()
        return self

    def __exit__(self, exc_type, exc_value, trace):  # with 구문 나갈 때 사용
        self.classes.clear()

gildong_hong = Student("Gildong Hong", 20224372)
with gildong_hong:
    gildong_hong.classes.add('CS201')
with Student("Gildong Hong", 20224372) as gildong_hong:
    gildong_hong.classes.add('CS201')

print(gildong_hong.name, gildong_hong.sid)  # Gildong Hong 20224372
# getter & setter 사용하기
class Circle(object):
    PI = 3.141592
    def __init__(self, raidus=3.):
self.radius = raidus
    def get_area(self):
        return Circle.PI * self.radius ** 2
    def set_area(self, value):
        self.radius = (value / Circle.PI) ** .5

circle = Circle(5.)
print(circle.get_area())
circle.set_area(10)
print(circle.radius)

# property 사용하기 (@ 사용)
class Circle(object):
    PI = 3.141592
    def __init__(self, raidus=3.):
        self.radius = raidus
    @property
    def area(self):
        return Circle.PI * self.radius ** 2
    @area.setter
    def area(self, value):
        self.radius = (value / Circle.PI) ** .5

circle = Circle(5.)
print(circle.area)
circle.area = 10.
print(circle.radius)

 


 

Inheritance & Polymorphism

명시적인 private & protected 범위가 없음모두 public

• private 변수/함수 이름 앞에 “__”를 붙임 (밑줄 2)

Ex) self.__name, self.__sid

• protected 변수/함수 이름 앞에 “_”를 붙임 (밑줄 1)

Ex) self._name, self._sid

class Student:
    def __init__(self, name: str, sid: int):
        self.name = name
        self.sid = sid
        self.classes = []

    def __str__(self):
        return self.name + "_" + str(self.sid)

    def take_class(self, class_name: str) -> None:
        self.classes.append(class_name)

class Master(Student):  # Student 상속
    def __init__(self, name: str, sid: int, professor: str):
        super().__init__(name, sid)  # 부모 클래스 생성자 접근, 정해진 부르는 타이밍은 없다.
        self.professor = professor

    def __str__(self):  # __str__ 재정의 → 다형성
        return super().__str__() + "_" + str(self.professor)

master = Master('Gildong Hong', 20224375, 'Prof Shin')
print(master)   # Gildong Hong_20224375_Prof Shin
print(super(Master, master).__str__()) # Gildong Hong_20224375 ==> super로 언제나 원하는 상위 클래스로 변환

# function visibility
class TestClass(object):
    def __init__(self):
        self.attr = 1 # Public 
        self._attr = 2 # Protected 
        self.__attr = 3 # Private
instance = TestClass()
print(dir(instance))
# 출력 결과
#['_TestClass__attr', '__class__', '__delattr__', 
# '__dict__', '__dir__', '__doc__', '__eq__', '__format__', 
# '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', 
# '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', 
# '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', 
# '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_attr', 'attr']

'AI NLP Study > Python' 카테고리의 다른 글

Python 자료구조와 Pythonic Programming  (0) 2022.01.10
Python Overview, Variable & Operator  (0) 2022.01.07

Data Structure

Lists

: 아무 타입이나 넣기 가능 + 길이가 정해져 있지 않음

  • List indexing: seq[index] 형태로 요소 하나 접근
  • List slicing: seq[start: end: step] 형태로 List 자르기 (end포함X)

 

Reserved Words VS Built-in functions VS Methods

  • 문법적 요소, 괄호X, 재정의 불가능  del, if-else, assert
  • 기본 정의된 함수, 별개 함수 사용, 재정의 가능, 편의성 향상 --> len(), range(), sum()
  • 객체 내 정의된 함수, .methods()로 접근, 해당 객체를 다룸 --> .append(), .insert(), .extend()

 

 

Tuple

  • Immutable list(불변 타입 리스트)
  • ( ) 를 사용
  • 함수에서 2개 이상 요소를 반환할 때 사용
  • Tuple안의 요소는 가변 타입일 수도 있음
  • String 타입일 때 일종의 문자 tuple로 생각 가능

 

Packing and Unpacking

  • Unpacking: * (Asterisk)로 남는 요소를 리스트로 남기기 가능


Dictionary

  • 매핑을 위한 데이터 구조 (key , value)
  • Key: 불변 타입만! + 중복이 불가능
  • Set: Dictionary의 Key만 집합처럼 모여 있는 형태 


Conditional Statements

  • if-elif-else
  • 삼항 연산자: [Value1] if [Condition] else [Value2]

 

Loop

  • While Statement: 조건을 만족하는 동안 출력
  • For Statement: 주어진 객체를 순환 (for [Element] in [Iterable])
  • break: 가장 바깥쪽의 반복문 나가기
  • continue: 가장 바깥의 반복문의 처음으로 되돌아가기 

 

Scope

  • Global scope: 최상위에 선언 == 다른 파일에서도 접근 가능
  • Local scope: 함수 안에 선언 == 상위함수에서 접근 불가 


Variable Capture

  • 상위 값이 바뀌면 하위 값이 바뀜
  • 파라미터가 없는데도 불구하고 함수내에서 바뀌어버림 --> 따라서, 파라미터를 써줘야 버그가 발생이 없어진다.
  • Closure = Factory형식
  • 파이썬에서 함수 = 일반 객체
  • 변수로 할당 가능

Decorator

  • 함수 하나를 인자로 받아  같은 형태의 함수를 반환하는 함수
  • @을 사용
  • Class를 사용할 시 Decorator에 인자 추가가 가능

Parameters

  • Function Parameters
  • Variable Length Parameter
  • Keyword Variable Length Parameter 

 



Pythonic Programming

Comprehension

  • result = [i * 2 for i in range(10)] // append
  • result = {str(i): i for i in range(10)} // key:value
  • result = {str(i) for i in range(10)} // add()
  • evens = [i for i in range(100) if i % 2 == 0] // 원하는 요소만 추가
  • result = [(i, j) for i in range(5) for j in range(i)] // 이중 for문
  • eye = [[int(i == j) for j in range(5)] for i in range(5)] // 다차원 배열 만들기

 

Generator

  • 요소를 하나씩 생성해서 반환하는 객체
  • Function에 yield를 사용하면 Generator가 된다
  • 괄호로 generator comprehension 형태로 선언 가능
  • even_generator = (i * 2 for i in range(100))

 

Lambda Function

  • 함수 이름 없이 빠르게 만들어 쓸 수 있는 함수  --> add = lambda a, b : a+b
  • seq = [6, -2, 8, 4, -5]    list(map(lambda x: x * 2, seq))  -->  [12, -4, 16, 8, -10]
  • seq = [6, -2, 8, 4, -5]    list(filter(lambda x: x > 0, seq))  -->  [6, 8, 4]

Python Overview

Features of python

  • 플랫폼 독립적인 인터프리터 언어
  • 완전 객체 지향 언어
  • 동적 타이핑 언어

 

Variable & Operator

How to Name Variables

  • 알파벳, 숫자, 언더스코어(_)로 선언
  • 변수명은 그 변수의 특징이 잘 살아 있게 하자(가독성)
  • 변수명은 대소문자가 구분
  • 변수명으로 쓸 수 없는 예약어가 존재

 

Out-place VS In-place 연산

  • Out-place: 명시적으로 새로운 객체 생성  // a = a + 1
  • In-place: 기존 객체를 수정 시도하고, 불가능할 시 새로운 객체 생성  //  a += 1

 

Primitive Data Types(Immutable / Mutable Types)

  • Immutable Type (불변 타입)이다
  • Python의 모든 것은 객체  Primitive Data Type 들 역시 객체
  • *불변 타입들은 저장된 값이 변하지 않는다!
  • 모든 타입은 Physical Memory 주소를 가르침
  • Primitive Data Type과 Tuple을 제외한 다른 모든 파이썬 객체는 Mutable Type (가변 타입)

파이썬에서 대입은 메모리 주소 복사의 원칙적 

  • 값을 복사하지 않고 같은 주소를 공유
  • immutable인데 수정이 필요하면 새로운 객체 생성

primitive data 크기에 따른 객체 할당 방법

  • 흔한 객체는 기존 객체를 들고 온다
  • 복잡한 값을 가지면 객체를 새로 형성

 

Types

* Dynamic Typing:

데이터 타입은 코드 실행 지점에서 정해진다 // a = 10  VS  int a = 10


* Implicit Type Conversion

: bool → int → float → complex 순서로 타입이 정해진다


* Explicit Type Conversion

: [Type]([value])로 명시적 형 변환


* Type Checking

: type(), isinstance([variable], [type])

 

+ Recent posts