객체지향 프로그래밍(파이썬)

Variety_·2021년 10월 11일
0

Python

목록 보기
10/12

객체지향 프로그래밍


객체를 이용한 프로그램을 객체는 속성과 기능으로 구성된다.

  • 객체(Object) = 속성(Attribute) + 기능(Function)

ex) 객체(자동차) = 속성(색상,길이,가격), 기능(전진,후진,정지 ...)

객체는 클래스에서 생성된다.

객체 사용의 장점 : 코드 재사용, 모듈화에 좋다

클래스 만들기

# 클래스 선언, 함수와 다르게 첫글자 대문자로 하는게 관례
class Car:
    
    # 생성자, 속성
    # init : 객체를 초기화해주는 생성자
    # self.color 여기에 있는 color는 self의 속성
    def __init__(self, color, length):
        self.color = color
        self.length = length
    # 기능
    def doStop(self):
        print("STOP!")
        
    # 객체 생성    
    car1 = Car('balck', 200)

객체의 속성값 변경

class NewGenerationPC:
    
    def __init__(self, name, cpu, memory, ssd):
        self.name = name
        self.cpu = cpu
        self.memory =memory
        self.ssd = ssd
        
    def doExcel(self):
        print("EXCEL RUN!!")
        
    def doPhotoshop(self):
        print("PHOTOSHOP RUN!!")
    
    def printPCInfo(self):
        print(f"self.name : {self.name}")
        
myPC = NewGenerationPC('myPC', 'i5', '16G', '256G')
myPC.printPCInfo()
fPC = NewGenerationPC('fPC', 'i7', '32G', '512G')

# 객체의 속성 변경, 아래처럼 변경가능  

myPC.cpu = 'i9'
myPC.memory = '64G'

# 아래처럼 생성자에 파라미터 초기화 안하고 생성해도 사용가능
class Cal:
    
    def __init__(self):
        self.number1 = 0
        self.number2 = 0
        self.result = 0
        
    def add(self):
        self.result = self.number1 + self.number2
        return self.result
    
cal1 = Cal()
cal1.number1, cal1.number2 = 1, 2
cal1.cad()
    

메모리와 객체에 대한 이해

  • 변수는 객체의 메모리 주소를 저장하고 이를 이용해서 객체를 참조한다.

=> 메모리 주소를 참조하기 때문에 shallow copy 문제가 발생한다.

class Robot:
    
    def __init__(self, color, height, weight):
        self.color = color
        self.height = height
        self.weight = weight
        
    def printRobotInfo(self):
        print(f"color : {self.color}")
        
rb1 = Robot('red', 200, 80)
rb2 = Robot('blue', 300, 120)
rb3 = rb1
  • 여기서 rb3의 내용을 바꾸면 rb1의 내용도 바뀜 => rb3에 rb1의 객체를 그대로 복사한게 아니라 주소값 복사한거라

객체의 복사 (얕은 복사, 깊은 복사)

  • 얕은 복사(Shallow copy) : 객체 주소를 복사하는 것으로 객체 자체가 복사되지 않는다.
  • 깊은 복사(Deep copy) : 객체 자체를 복사하는 것으로 또 하나의 객체가 만들어진다.
class TemCls:
    
    def __init__(self, n ,s):
        self.number = n
        self.str = s
    
    def printClsInfo(self):
        print(f"self.number : {self.number}")

# 얕은 복사        
tc1 = TemCls(10, 'Hello')
tc2 = tc1

# 깊은 복사
import copy

tc1 = TemcCls(10, "hello")
tc2 = copy.copy(tc1)

List 깊은복사

import copy

scores = [9, 8, 7, 6, 5]
scoresCopy = []

scoresCopy = scores

# id() 함수 : 주소값 알려줌
print(f"id(scores) : {id(scores)}")

# 깊은 복사
scoresCopy = scores.copy()

클래스 상속

  • 상속 : 클래스는 또 다른 클래스를 상속해서 내 것처럼 사용할 수 있다.
class NormalCar:
    
    def drive(self):
        print('[NormalrCar] drive() called!')
        
    def back(self):
        print('[NormalCar] back() called!')

# 상속받을 클래스를 괄호() 안에 명시하면 상속 됨        
class TurboCar(NormalCar):
    
    def turbo(self):
        print('[TurboCar] turbo() called!')
        
myTurboCar = TurboCar()
myTurboCar.turbo()
myTurboCar.back()

생성자

  • 객체가 생성될 때 생성자를 호출하면 __init__()가 자동 호출된다.

cal = Calculator() => Calculator()생성자 호출 => Calculator__init__() 호출

  • __init__ 메소드가 생성자 초기화 시켜줌
class Calculator:
    
    def __init__(self, n1, n2):
        print('[Calclator] __init() called!!')
        self.num1 = n1
        self.num2 = n2
        
cal = Calculator(10, 20)

# 또는 아래와 같이 고정해서 초기화 가능
class Calculator:
    
    def __init__(self):
        print('[Calclator] __init() called!!')
        self.num1 = 10
        self.num2 = 100

super()

  • 상위 클래스의 속성을 초기화하기 위해서 super()을 이용한다.
class P_class:
    
    def __init__(self, pNum1, pNum2):
        print('[P_class] __init__() called')
        self.pNum1 = pNum1
        self.pNum2 = pNum2
        
class C_class(P_class):
    
    def __init__(self, cNum1, cNum2):
        print('[C_class] __init__()called')
        self.cNum1 = cNum1
        self.cNum2 = cNum2
        
# 방법 1
class C_class(P_class):
    
    def __init__(self, cNum1, cNum2):
        print('[C_class] __init__()called')
        # 강제로 호출
        P_class.__init__(self, cNum1, cNum2)
        
        self.cNum1 = cNum1
        self.cNum2 = cNum2
        
# 방법 2

class C_class(P_class):
    
    def __init__(self, cNum1, cNum2):
        print('[C_class] __init__()called')
        # super() 사용
        super().__init__(cNum1, cNum2)
        
        self.cNum1 = cNum1
        self.cNum2 = cNum2

다중 상속

  • 2개 이상의 클래스를 상속

    ex) Car가 car01, car02, car03 여러개를 상속받을 수 있음

class Car01:
    
    def drive(sef):
        print('drive() method called!')
        
class Car02:
    
    def turbo(sef):
        print('turbo() method called!')

class Car03:
    
    def fly(sef):
        print('fly() method called!')
        
        
class Car(Car01, Car02, Car03):
    
    def __init__(self):
        pass
    
myCar = Car()
myCar.drive()
  • 그러나 다중상속을 사용시 동일한 메소드가 있으면 문제가 생길 수 있음!

오버라이딩

  • 오버라이딩 : method를 재정의, 하위 클래스에서 상위 클래스의 메서드를 재정의(override)한다.
class Robot:
    
    def __init__(self, c):
        self.color = c
    
    def fire(self):
        print("총알 발사!")
        
class NewRobot(Robot):
    
    def __init__(self, c):
        super().__init__(c)
    
    def fire(self):
        print("레이저 발사!!")
        
new = NewRobot('red')
new.fire()

추상클래스

  • 상위 클래스에서 하위 클래스에 메서드 구현을 강요한다.
  • 상위 클래스에서는 메서드를 선언만 해놓고 하위클래스에서 메서드를 구체화 해야함
  • 주로 큰틀에서 봤을 때는 비슷한 느낌이지만 세부기능은 다른 클래스를 만들 때 사용
  • ex) 상위클래스 자동차, 하위클래스 전기차, 가솔린차 등등

# ABCMeta : 강제성을 띄게하는 상위클래스
# abstractedmethod : 강제로 구현하게 하는 메소드 데코레이션(@abstractmethod)을 위한 모듈

from abc import ABCMeta
from abc import abstractmethod

class AirPlane(metaclass=ABCMeta):
    
    @abstractmethod
    def flight(self):
        pass
    
class AirLiner(AirPlane):
    
    def flight(self):
        print('난다난나나닫다')

0개의 댓글