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

+ Recent posts