Programming & Machine Learning/Python X 머신러닝

파이썬 기초 문법 - 3 (클래스와 오브젝트)

Yamarae 2017. 7. 27. 02:36

클래스와 오브젝트

#################################################################
#################################################################

### 클래스에서 self, cls, static의 역할
# class는 붕어빵 빵틀, object는 붕어빵이라고 비유가 가능.
# self는 붕어빵 각각이 가지는 속성이고, cls는 붕어빵 빵틀이 가지는 속성임.
# 클래스의 멤버변수를 선언할때 아래처럼 선언하면 빵틀 변수가 되는 것이고,
# init 에서 self로 선언하면 붕어빵의 변수가 되는 것이다.
class InstanceCounter:
    count = 0
    count2 = 0
    
    def __init__(self):
        self.count3 = 0
        InstanceCounter.count += 1
        self.count2 += 1
        
    @classmethod
    def print_instance_count(cls):
        print(cls.count)
        print(cls.count2)
        
    @staticmethod
    def print_static_count():
        print(InstanceCounter.count)
        print(InstanceCounter.count2)
        
a = InstanceCounter() 
InstanceCounter.print_instance_count()
InstanceCounter.print_static_count()

b = InstanceCounter()
InstanceCounter.print_instance_count()
InstanceCounter.print_static_count()

c = InstanceCounter()
c.print_instance_count()
InstanceCounter.print_static_count()

#################################################################
#################################################################

### 예제2
class Car:
    count = 0
    
    def __init__(self):
        Car.count += 1
        
    def print(self):
        print(self.count)
        
a = Car()
a.print()
b = Car()
b.print()
c = Car()
c.print() 
# --> init 할때마다 붕어빵 빵틀의 속성 자체가 변하고 있음,
# 새로 Car 오브젝트를 생성하면 붕어빵의 기본 count가 빵틀에서 나온 속성으로 설정됨.

#################################################################
#################################################################

### 클래스의 퍼블릭, 프라이빗
class HasPrivate:

    def __init__(self):
        self.public = "Public"
        self.__private = "Private"

    def print_from_internal(self):
        print(self.public)
        print(self.__private)
        
obj = HasPrivate()
obj.print_from_internal()
print(obj.public)
print(obj.__private) # error -> __membervariable은 외부접근 불가.


### 상속
class Base:
    def base_method(self):
        print("base_method")
                        
class Derived(Base):
    pass

base = Base()
base.base_method()
derived = Derived()
derived.base_method()

#################################################################
#################################################################

### super를 이용한 상속
class A:
    no_init = "hello no init"
    
    def __init__(self):
        self.hello = "hello"
        print("A.__init__()") 
        
        
class B(A):
    def __init__(self):
        #super().__init__()
        print("B.__init__()")
        
b = B()
b.hello
b.no_init
# super로 부모클래스를 init해주지 않으면 부모의 init에서부터 생성된 속성 사용 불가
# super로 init 안해줘도 no_init 같은 속성은 사용 가능.


### 다중상속
class A:
    pass

class B:
	pass

class C(A,B):
	pass

# super와 오버라이딩을 이용하면, 다중상속에서 다이아몬드 상속 문제를 해결 가능함.

#################################################################
#################################################################

### 데코레이터
# __call__() 메소드는 객체를 함수 호출 방식으로 사용하게 만듬.

# 첫번째 방법
class Callable:
    
    def __call__(self):
        print("I am called.")
        
obj = Callable()
obj()

class MyDecorator:

    def __init__(self, f):
        print("initialize decorator")
        self.func = f
        
    def __call__(self):
        print("begin :{0}".format(self.func.__name__))
        self.func()
        print("end :{0}".format(self.func.__name__))
        
def print_hello():
    print("hello world!")
    
obj = MyDecorator(print_hello)
obj()

# 두번째 방법
class MyDecorator: 
    
    def __init__(self, f):
        print("Initializing MyDecorator...") 
        self.func = f
        
    def __call__(self):
        print ("Begin :{0}".format( self.func.__name__)) 
        self.func()
        print ("End :{0}".format(self.func.__name__))
    
@MyDecorator
def print_hello(): 
    print("Hello.")
    
print_hello()

#################################################################
#################################################################

### 추상클래스와 메서드 implementation

from abc import ABCMeta
from abc import abstractmethod

class AbstractDuck(metaclass=ABCMeta):

    @abstractmethod 
    def Quack(self):
        pass
    

class Duck(AbstractDuck):
    
    def Quack(self):
        print("implementation")
        
duck = Duck()
duck.Quack()