[Python] 객체지향 프로그래밍

·2023년 3월 7일
0

[Python] 제로베이스

목록 보기
9/11
post-thumbnail

✒️ 객체지향 프로그래밍

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

  • 객체 (Object) = 속성(Attribute) + 기능(Function)
  • 객체는 클래스에서 생성된다.

객체 사용의 장점

코드 재사용, 모듈화에 좋다.

CAR A (배터리 일체형) -> 부품 결합도 높음
CAR B (배터리 교체형) -> 부품 결합도 낮음 -> 가장 이상적인 프로그램
CAR C (배터리 충전형) -> 부품 결합도 높음

✒️ 클래스와 객체 생성

클래스는 class 키워드와 속성(변수) 그리고 기능(함수)를 이용해서 만든다.

# class Car
class Car:
    def __init__(self, c, len):
        self.color = c
        self.length = len

    def doStop(self):
        print('STOP!')

    def doStart(self):
        print('START!')

    def printCarInfo(self):
        print(f'color : {self.color} length : {self.length}')


----------------------------------------------------------------

car = Car('red', 200)

print(car.color, " ", car.length)


📌결과
color : red length : 200

✍️실습

비행기 클래스 만들고 객체 5개를 생성
class Plane:

    def __init__(self, country, date):
        self.country = country
        self.date = date

    def doFly(self):
        print('이륙합니다')

    def doArrive(self):
        print('착륙합니다')

    def printInfo(self):
        self.doFly()
        print(f'이번 여행지는 {self.country} 입니다 ')
        print(f'오늘 날짜는 {self.date} 입니다 ')
        self.doArrive()


plane = Plane('CANADA', datetime.datetime.now())
plane.printInfo()

📌결과
이륙합니다
이번 여행지는 CANADA 입니다 
오늘 날짜는 2023-03-07 12:33:19.437442 입니다 
착륙합니다

객체의 속성 변경

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 doPyCharm(self):
        print('DO Python ! ')

    def printInfo(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', '250G')
myPc.doExcel()
myPc.doPyCharm()
myPc.printInfo()
print('-' * 20)
myPc.name = 'New PC'
myPc.printInfo()


📌결과
Excel RUN ! 
DO Python ! 
name : myPc
cpu : i5
memory : 16G
ssd : 250G
--------------------
name : New PC
cpu : i5
memory : 16G
ssd : 250G

✒️ 객체와 메모리

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

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}')
        print(f'weight : {self.weight}')
        print(f'height : {self.height}')


rb1 = Robot('red', 200, 80)
rb2 = Robot('blue', 300, 120)
rb3 = rb1  # rb3과 rb1의 주소가 같아, 메모리 주소가 copy 됨

rb1.printRobotInfo()
rb2.printRobotInfo()
rb3.printRobotInfo()

rb1.color = 'green'
rb1.height = 400
rb1.weight = 150

rb1.printRobotInfo()
rb2.printRobotInfo() 
rb3.printRobotInfo() #rb1과 출력 결과가 동일 




✍️실습

국어, 영어, 수학 점수를 입력받아 리스트에 저장하고 원본을 유지한 상태로 복사본을 만들어 과목별 점수를 10% 올렸을 경우에 평균 출력
scores = [int(input('국어 점수 : ')),
          int(input('영어 점수 : ')),
          int(input('수학 점수 : '))]
copy = scores.copy()

for idx, score in enumerate(scores):  # enumerate : 인덱스와 원소 동시 접근

    copy[idx] = math.trunc(copy[idx] * 1.1)
    copy[idx] = 100 if copy[idx] > 100 else copy[idx]

print(scores)
print(copy)

print(f'이전 평균 : {round(sum(scores) / len(scores), 2)}')
print(f'이후 평균 : {round(sum(copy) / len(copy), 2)}')



📌결과
국어 점수 : 86
영어 점수 : 90
수학 점수 : 88
[86, 90, 88]
[94, 99, 96]
이전 평균 : 88.0
이후 평균 : 96.33


✒️ 얕은 복사와 깊은 복사

얕은 복사란, 객체 주소를 복사하는 것으로 객체 자체가 복사되지 않는다.

깊은 복사란, 객체 자체를 복사하는 것으로 또하나의 객체가 만들어진다.

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

tc1.printClsInfo()
tc2.printClsInfo()

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

tc1.printClsInfo()
tc2.printClsInfo()

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

tc2.number = 3.14
tc2.str = 'bye'

tc1.printClsInfo()
tc2.printClsInfo()

깊은 복사 하는 방법

  • copy() 함수 이용
  • for 문 이용
  • extend() 함수 이용
  • [ : ] 슬라이스 이용
scores = [9, 8, 5, 7, 6, 10]
scoresCopy = []

#for 문 이용 
for s in scores:
    scoresCopy.append(s)

#extend() 
scoresCopy.extend(scores)

#copy()
scoresCopy = scores.copy()

#슬라이스
scoresCopy = scores[:]

✍️실습

선수의 원본 점수를 이용해서 평균을 출력하소, 최고값과 최저값을 제외한 평균을 출력하는 프로그램

playerScore = [8.1, 9.3, 7.8, 7.6, 8.4, 9.1]
copyScore = []
copyScore.extend(playerScore)

copyScore.sort()
copyScore.pop(0)
copyScore.pop()

rint(f'원본 : {playerScore}')
print(f'사본 : {copyScore}')
print(f'원본 평균 : {round(sum(playerScore) / len(playerScore), 2)}')
print(f'사본 평균 : {round(sum(copyScore) / len(copyScore), 2)}')



📌결과
원본 : [8.1, 9.3, 7.8, 7.6, 8.4, 9.1]
사본 : [7.8, 8.1, 8.4, 9.1]
원본 평균 : 8.38
사본 평균 : 8.35

✒️ 클래스와 상속

클래스는 또 다른 클래스를 상속해서 내것처럼 사용할 수 있다.

class NormalCar:

    def drive(self):
        print('[NormalCar drive() called!')

    def back(self):
        print('[NormalCar back() called!')


class TurboCar(NormalCar):

    def turbo(self):
        print('[TurboCar] turbo called!')


myTurbo = TurboCar()
myTurbo.turbo()
myTurbo.drive()
myTurbo.back()


📌결과
[TurboCar] turbo called!
[NormalCar drive() called!
[NormalCar back() called!

✍️실습

덧셈, 뺼셈 기능이 있는 클래스를 만든 후 상속받아 곱셈, 나눗셈 실행
class SuperCalculator:
    def add(self, n1, n2):
        return print(n1 + n2)

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


class ChildCalculator(SuperCalculator):
    def mul(self, n1, n2):
        return print(n1 * n2)

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


child = ChildCalculator()

child.mul(15, 5)
child.div(15, 5)
child.add(15, 5)
child.sub(15, 5)


📌결과
75
3.0
20
10

✒️ 생성자

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

코드를 class Calculator:

    def __init__(self):
        print('Calculator 생성자 호출')


cal = Calculator()


📌결과
Calculator 생성자 호출

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

class Calculator:

    def __init__(self, n1, n2):
        print('Calculator 생성자 호출')
        self.num1 = n1
        self.num2 = n2


cal = Calculator(10, 20)
print(f'num1 : {cal.num1}\tnum2 : {cal.num2}')

📌결과
Calculator 생성자 호출
num1 : 10	num2 : 20

super()

상위 클래스의 속성을 초기화하기 위해서 super()를 이용한다.

상위 클래스의 기능은 속성을 초기화 하지 않아도 사용할 수 있지만 속성은 초기화 후 사용 가능

class Parents:
    def __init__(self, pNum1, pNum2):
        print('Parents Class Init()')

        self.pNum1 = pNum1
        self.pNm2 = pNum2


class Child(Parents):
    def __init__(self, cNum1, cNum2):
        print('Child Class Init()')

        # Parents.__init__(self, cNum1, cNum2)
        super().__init__(cNum1, cNum2)

        self.cNum1 = cNum1
        self.cNum2 = cNum2


child = Child(23, 15)



📌결과
Child Class Init()
Parents Class Init()

✍️실습

중간고사 클래스와 기말고사 클래스를 상속관계로 만들고 각각의 점수를 초기화, 총점 및 평균을 반환하는 기능 만들기

class MidExam:
    def __init__(self, korMid, engMid, mathMid):
        self.korMid = korMid
        self.engMid = engMid
        self.mathMid = mathMid


class FinalExam(MidExam):

    def __init__(self, korMid, engMid, mathMid, korFinal, engFinal, mathFinal):
        self.korFinal = korFinal
        self.engFinal = engFinal
        self.mathFinal = mathFinal
        super().__init__(korMid, engMid, mathMid)
        self.scores = [self.korMid, self.engMid, self.mathMid, self.korFinal, self.engFinal, self.mathFinal]

    def getTotal(self):
        return sum(self.scores)

    def getAvg(self):
        return round(self.getTotal() / len(self.scores), 2)


exam = FinalExam(int(input('중간 국어 : ')), int(input('중간 영어 : ')), int(input('중간 수학 : ')),
                 int(input('기말 국어  : ')), int(input('기말 영어 : ')), int(input('기말 수학 : ')))

print(f'총점 : {exam.getTotal()}')
print(f'평균 : {exam.getAvg()}')


📌결과
중간 국어 : 85
중간 영어 : 90
중간 수학 : 100
기말 국어  : 80
기말 영어 : 80
기말 수학 : 90
총점 : 525
평균 : 87.5

✒️ 다중 상속

2개 이상의 클래스를 상속한다.

class Car01:
    def drive(self):
        print('drive method called()')


class Car02:
    def turbo(self):
        print('turbo method called()')


class Car03:
    def fly(self):
        print('fly method called()')


class Car(Car01, Car02, Car03):
    def __init__(self):
        pass


myCar = Car()
myCar.drive()
myCar.fly()
myCar.turbo()

📌결과
drive method called()
fly method called()
turbo method called()

❗다중 상속의 사용은 지양하자

✒️ 오버라이딩

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

class Robot:
    def __init__(self, c, h, w):
        self.color = c
        self.height = h
        self.width = w

    def fire(self):
        print('미사일 발사!')

    def printInfo(self):
        print(f'color : {self.color}')
        print(f'width : {self.width}')
        print(f'height : {self.height}')


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

    def fire(self):
        print('미사일 발사 중지!')


myRobot = NewRobot('red', 200, 300)
myRobot.printInfo()
myRobot.fire()

📌결과
width : 300
height : 200
미사일 발사 중지!

✍️실습

삼각형의 넓이를 계산하는 클래스를 만들고 이를 상속하는 클래스에서 getArea() 오버라이딩
class TriangleArea:
    def __init__(self, w, h):
        self.width = w
        self.height = h

    def printInfo(self):
        print(f'width : {self.width}')
        print(f'height : {self.height}')

    def getArea(self):
        print('삼각형 넓이 : ', end='')
        return self.width * self.height / 2


class CustomArea(TriangleArea):
    def __init__(self, w, h):
        super().__init__(w, h)

    def getArea(self):
        return str(super().getArea()) + 'c㎡'


area = CustomArea(15, 16)
print(area.getArea())

📌결과
삼각형 넓이 : 120.0c㎡

✒️ 추상클래스

상위 클래스에서 하위 클래스에 메서드 구현을 강요한다.

from abc import ABCMeta
from abc import abstractmethod


class AirPlane(metaclass=ABCMeta):
    @abstractmethod
    def flight(self):
        pass

    def forward(self):
        print('전진')

    def backward(self):
        print('후진')


class AirLine(AirPlane):
    def __init__(self, c):
        self.color = c

    def flight(self):
        print('시속 400km/h 비행')


class fighterPlane(AirPlane):
    def __init__(self, c):
        self.color = c

    def flight(self):
        print('시속 700km/h 비행')


al = AirLine('red')
al.flight()

fl = fighterPlane('red')
fl.flight()

📌결과
시속 400km/h 비행
시속 700km/h 비

✍️실습

계산기 추상 클래스를 만들고 이를 이용해 새로운 클래스 생성
from abc import ABCMeta
from abc import abstractmethod


class Calculator(metaclass=ABCMeta):

    @abstractmethod
    def add(self, n1, n2):
        pass

    @abstractmethod
    def sub(self, n1, n2):
        pass

    @abstractmethod
    def mul(self, n1, n2):
        pass

    @abstractmethod
    def div(self, n1, n2):
        pass


class DevelopCalculator(Calculator):

    def add(self, n1, n2):
        print(f'{n1} + {n2} : {n1 + n2}')

    def sub(self, n1, n2):
        print(f'{n1} - {n2} : {n1 <- n2}')

    def mul(self, n1, n2):
        print(f'{n1} * {n2} : {n1 * n2}')

    def div(self, n1, n2):
        print(f'{n1} / {n2} : {n1 / n2}')


devCal = DevelopCalculator()
devCal.add(10, 20)
devCal.sub(10, 20)
devCal.mul(10, 20)
devCal.div(10, 20)


📌결과
10 + 20 : 30
10 - 20 : -10
10 * 20 : 200
10 / 20 : 0.5
profile
개발하고싶은사람

0개의 댓글