python - (3) 객체지향 프로그래밍

jun hyeon·2023년 8월 8일

python

목록 보기
16/21
post-thumbnail

자료 참조는 제로베이스

객체지향 프로그래밍

  • 객체 = 속성 + 기능 ex) 계산기 = 숫자 + 덧셈
  • 객체는 클래스에서 생성된다.

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

  • ex)
    자동(배터리일체형) : 부품결합도 높음 (배터리가 잘못되면 차를 다시 생산해야한다.)
    자동차(배터리교체형) : 부품결합도 낮음 (모듈화, 배터리(코드(성능, 기능, 부품)를 골라서 사용가능))
    => 부품결합도가 낮은 것이 재사용, 모듈화에 좋다.

▶ 클래스 만들기

클래스는 생성자, 기능으로 이루어진다. 선언부에 class키워드 사용.


▶ 객체 만들기

객체는 생성자를 호출하여 만든다.

다른 예시 코드 :

class Airplane:
    def __init__(self,col,no): # 생성자
        self.color = col
        self.number = no

    def arrive(self): # 기능
        print('도착')

    def depart(self): # 기능
        print('출발')

    def Info(self): # 기능
        print(f'색 : {self.color}, 편명 : {self.number}')

koreanAir = Airplane('skyblue', 500)
asiana = Airplane('gold', 300)
airBusan = Airplane('navy', 200)
jinAir = Airplane('green', 600)

koreanAir.Info()
asiana.depart()
airBusan.Info()
jinAir.arrive()
#출력
색 : skyblue, 편명 : 500
출발
색 : navy, 편명 : 200
도착

▶ 객체 속성 변경하기

객체 바로 뒤 .입력, 변경하고자 하는 속성에 값을 다시 할당하면 된다.

class NewGenerationPC:

    def __init__(self, name, cpu, memory, ssd):
        self.name = name # 앞의 name은 NewGenerationPC클래스로부터 만들어질 객체의 속성, 뒤의 name은 매개변수
        self.cpu = cpu
        self.memory = memory
        self.ssd = ssd
        
    def Info(self):
        print(f'name : {self.name}')
        print(f'cpu : {self.cpu}')
        print(f'memory : {self.memory}')
        print(f'ssd : {self.ssd}')
        
myPC = NewGenerationPC('myPc', 'i5', '16G', '256G') # 객체생성
myPC.Info()

myPC.cpu = 'i9' # 속성에 접근, 할당 
myPC.memory = '64G' # '.'(접근 연산자)
myPC.ssd = '1T'
myPC.Info()
#출력
name : myPc
cpu : i5
memory : 16G
ssd : 256G
name : myPc
cpu : i9 - 속성 변경됨
memory : 64G - 속성 변경됨
ssd : 1T - 속성 변경됨

▶ 객체와 메모리

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

  • ex) myCar = Car() -> myCar에 객체가 저장되는 것이 아님. 메모리 주소를 참조하는 것.
  • ex) 'myCar.info()' : 변수가 참조하고 있는 메모리의 주소에 찾아가 기능을 호출하는 것임.

▶ 깊은 복사, 얕은 복사

  • 얕은 복사란, '객체 주소를 복사'하는 것으로 객체 자체가 복사되지 않는다.
  • 깊은 복사란, '객체 자체'를 복사하는 것으로 또 하나의 객체가 만들어진다.
class TemCls:

    def __init__(self, n, s):
        self.number = n
        self.str = s

    def Info(self):
        print(f'number : {self.number}')
        print(f'str : {self.str}')

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

tc1.Info()
tc2.Info()

tc2.number = 3.14
tc2.str = 'Bye'

tc1.Info()
tc2.Info()

import copy

tc1 = TemCls(10, 'Hello')
tc2 = copy.copy(tc1) #깊은 복사 #객체 자체를 복사

tc1.Info()
tc2.Info()

tc2.number = 3.14
tc2.str = 'Bye'

tc1.Info()
tc2.Info()
#출력
number : 10
str : Hello
number : 10
str : Hello #얕은 복사

number : 3.14 #하나의 속성을 변경하면 참조를 같이하는 다른 하나의 변수의 값도 변한다.
str : Bye
number : 3.14 
str : Bye

number : 10
str : Hello
number : 10
str : Hello #깊은 복사

number : 10 #값만 같은 두 객체이기 때문에, 하나의 속성값을 바꿔도 변하지 않는다.
str : Hello
number : 3.14
str : Bye 

▶ 상속

클래스는 또 다른 클래스를 상속해서 내 것처럼 사용할 수 있다.
상속받을 클래스는 클래스이름 옆에 클래스명 괄호 안에 '(상속해주는 클래스)' 형태를 띤다.

class CalSuper:

    def add(self, n1, n2):
        return n1 + n2

    def sub(self, n1, n2):
        return n1 - n2

class CalChild(CalSuper): # CalSuper를 상속받음.

    def mul(self, n1, n2):
        return n1 * n2

    def div(self, n1, n2):
        return n1 / n2

calchild = CalChild()
print(f'cal add : {calchild.add(10,20)}') # 상속받은 CalSuper의 함수 호출
print(f'cal sub : {calchild.sub(10,20)}') # 상속받은 CalSuper의 함수 호출
print(f'cal mul : {calchild.mul(10,20)}')
print(f'cal div : {calchild.div(10,20)}')
#출력
cal add : 30
cal sub : -10
cal mul : 200
cal div : 0.5

▶ 생성자

객체 생성 시 생성자를 호출하면, ' __init__() ' 이 자동으로 호출된다.

class Calculator:

    def __init__(self, n1, n2):
        print('[Calculator] __init__() called!!')
        self.num1 = n1
        self.num2 = n2

cal = Calculator(10, 20)
#출력
[Calculator] __init__() called!!

' __init__() ' 은 속성을 초기화 한다.

class Calculator:

    def __init__(self, n1, n2):
        print('[Calculator] __init__() called!!')
        self.num1 = n1
        self.num2 = n2

cal = Calculator(10, 20) #속성이 있을때, 생성자에 값을 넣어줘야한다. - 속성초기화.
print(f'num1 : {cal.num1}')
print(f'num2 : {cal.num2}')
#출력
[Calculator] __init__() called!!
num1 : 10 # 속성값 초기화 됨.
num2 : 20 # 속성값 초기화 됨.

super()은 상위 클래스의 속성을 초기화 할 떄 이용한다.
super()를 쓰지 않고 강제로 __init__()을 써도 된다.

class Car:

    def __init__(self, color, type):
        self.color = color
        self.type = type

    def drive(self):
        print('Let\'s go!!!!')

    def reverse(self):
        print('Let\'s back~~~~')

class Suv(Car):

    def __init__(self, color, type):
        super().__init__(color, type) # 상위클래스 속성 초기화
        #Car.__init__(self, color, type) # 방법2 상위 init 강제호출

suv1 = Suv('blue', 'benz')

print(f'color is {suv1.color}')
print(f'color is {suv1.type}')
suv1.drive()
#출력
color is blue
color is benz
Let's go!!!!

▶ 오버라이딩

하위 클래스에서 상위클래스의 메서드를 재정의 한다.

class Robot:

    def __init__(self, c, h, w):
        self.color = c
        self.height = h
        self.weight = w

    def fire(self):
        print('fire!!')

class NewRobot(Robot):

    def __init__(self, c, h, w):
        super().__init__(c, h, w)

    def fire(self):
        print('lazer!!') #오버라이딩. 재정의 함.

myRobot = NewRobot('red', 200, 300)
myRobot.fire()
#출력
lazer!!

▶ 추상클래스

추상 클래스는 상속 받은 하위 클래스에 미완전한 메서드의 구체화를 강요한다. 구현하지 않으면 에러.

  • 비유를 하자면, 비행기를 상속받아서 각자 알아서 입맛에(전투기, 여객기 등) 고쳐써라.
#추상클래스 문법
from abc import ABCMeta
from abc import abstractmethod
class Airplane(metaclass=ABCMeta):

    @abstractmethod
    def flight(self):
        pass

class Airliner(Airplane):

    def flight(self):
        print('400km/h fly!!')

class Airforce(Airplane):

    def flight(self):
        print('900km/h fly!!')

air1 = Airliner()
air2 = Airforce()
air1.flight()
air2.flight()
#출력
400km/h fly!!
900km/h fly!!

0개의 댓글