OOP(Object Oriented Programming), 클래스 설계
CS 섹션에 들어오고 하루 이틀 공부해보면서 파이썬 공부를 하는건가보다 싶었는데 그게 아니었다.
앞으로 남은 섹션 공부하면서 이런 맥락을 기억하도록 하자. 지엽적인 것에 빠지지 말고 큰 그림을 생각할 줄 알아야 한다.
4번 실습과제
의 Part2
에 적어두었으니 보도록 하자. OOP에 대해서는 나중에 공부노트로 따로 정리해보는 시간을 가지는게 나을 듯 싶다. 대신 오늘 들은 것 중 기억할만한 몇 가지만 옮겨와 보자면..
OOP 및 파이썬의 관련 기능들 또한 이런 맥락에서 생각해보면 더 잘 기억하기 쉬울 것 같다.
데이터 캡슐화와 접근제어
name - public - 어디서나 접근 가능
_name - Protected - public과 비슷하지만 웬만하면 밖에선 가져다 쓰지 말았음 좋겠다~ 는 의미
__name - Private 안 보여줄거고 접근도 안되게 할거야!
파이썬의 자료형도 하나의 클래스이다.
<class 'int'>
식으로 출력되는 걸 볼 수 있다. 어젠가 그림에 class 안에 모듈있고 함수 있던거 기억난다. split
함수는 str(문자열)에 대해서만 쓸 수 있다. 만약 list에 쓰면 'list object has no attribute 'split'
과 같은 에러를 볼 수 있는데 이 말은 뭐냐? 바로 split이란 함수는 str이라는 클래스 안에 있다는 것이다! 오늘 OOP 관련 자주 들었던 말도 있다.
클래스/객체/인스턴스란?
QnA 세션 간 작성해보았던 것이다.
# Car 클래스 선언
class Car:
pass
# 객체 선언
my_car = Car()
sm_car = Car()
# 객체의 속성값 설정
my_car.color = 'red'
sm_car.color = 'yellow'
print('차 색상 = ', my_car.color) # 차 색상 = red
print('차 색상 = ', sm_car.color) # 차 색상 = yellow
# __init__() 초기화 함수
# 객체를 생성하는 것과 동시에 속성값을 지정할 수 있다.
# Car 클래스 선언
class Car:
def __init__(self, color):
self.color = color
my_car = Car('blue') # 기본 속성값을 지정해서 객체를 선언해줘야 한다.
print('차 색상 = ', my_car.color) # 차 색상 = blue
'''
class Car:
def __init__(self, color = 'yellow'): # 이렇게 하면 컬러 디폴트도 지정 가능.
self.color = color
'''
__init__
함수는 잘 알고 있는 것처럼 클래스가 실행되자마자 실행되는 기본 기능이라고 생각하면 된다. 즉, 위 코드에서는 인스턴스를 생성할 때 color
를 지정해줘야 한다. 안 그럼 에러.class Gun():
def __init__(self):
self.bullet = 0
def charge(self, num): # 장전
self.bullet += num # 추가 장전하면 이전에 가지고 있던 총알 수에 더해서 되어야하니까!
def shoot(self, num):
for i in range(num):
if self.bullet > 0:
print('탕!')
self.bullet -=1
elif self.bullet == 0:
print("총알이 없습니다.")
break
gen = Gun()
# 장전
gen.charge(5)
# shoot
gen.shoot(2)
gen.shoot(3)
gen.shoot(2)
"""
탕!
탕!
탕!
탕!
탕!
총알이 없습니다.
"""
gen.charge(5)
gen.charge(7)
print(gen.bullet)
gen.shoot(3)
print(gen.bullet)
"""
12
탕!
탕!
탕!
9 # 이렇게까지 잘 되어야 한다! 여기 놓치기 쉬울 것 같음.
"""
charge
하면 그만큼 bullet
의 수가 증가하고, shoot
을 하면 '탕!'
을 프린트하며 bullet 수를 줄여나가다가 다 소진하면 "총알이 없습니다"
를 출력하는거다."""
고릴라 클래스를 구현해서 고릴라 객체를 만드시오!
gorila_1 = Gorilla()
gorila_1.eat(10)
바나나를 10개를 먹었습니다.
gorila_1.shout(3)
우와 ~~~~
우와 ~~~~
우와 ~~~~
# 소리 지를 떄마다 바나나 하나씩 소진
바나나가 다 소진 되었는데 또 소리를 지르려고 하면
배가고파 소리를 지를 수 없습니다. 메세지가 출력되게하시오~
"""
class Gorilla:
def __init__(self):
self.banana = 0
def eat(self, num):
self.banana += num
print(f"바나나를 {num}개를 먹었습니다")
def shout(self, num):
for i in range(num):
if self.banana > 0:
print('우와 ~~~~')
self.banana -= 1
elif self.banana == 0:
print("배가 고파 소리를 지를 수 없습니다.")
break
오늘은 주로 class를 통해 특정 기능을 구현하는 과제였다. 프로그램 설계의 의미로 봐도 될 것 같다. 오늘은 시간 관계상 기본과제만 했다.
[part1]
"""
Bare Minimum Requirements
요구사항:
아래 문제들을 확인하며 하나씩 문제를 풀어주세요.
"""
from unicodedata import name
class CarOwner:
"""
자동차 주인을 나타내는 클래스입니다.
자동차 주인은 이름(name)을 가지고 있으며
자동차 주인은 concentrate 메소드를 통해 이름 + ' can not do anything else'를 반환해야합니다.
"""
def __init__(self, name):
"""
문제 1.
CarOwner 클래스의 생성자 메소드를 작성해주세요.
매개변수를 수정하거나 추가하지 말아주세요.
"""
self.name = name
def concentrate(self):
"""
문제 2.
자동차 주인 이름에 따라
'{자동차주인이름} can not do anything else'문구를 반환해주는 메소드를 작성해주세요.
"""
return f"{self.name} can not do anything else"
class Car:
"""
자동차를 나타내는 클래스입니다.
자동차는 주인(owner)을 가지고 있으며, 주인은 CarOwner를 통해서 생성됩니다.
자동차는 drive 메소드를 통해
자동차 주인이 집중하고 있으며(concentrate), 누가 운전하고 있는지 반환해야합니다.
'{자동차주인이름} is driving now.'
"""
def __init__(self, owner_name):
"""
문제 3.
Car 클래스의 생성자 메소드를 작성해주세요.
매개변수를 수정하거나 추가하지 말아주세요
"""
self.owner = CarOwner(owner_name)
# 어떻게 가져올 수 있을까 헷갈렸는데.. 이렇게 인스턴스 생성해서 쓸 수 있는거 기억하자.
def drive(self):
"""
문제 4.
자동차 주인이 집중하고 있으며, 자동차 주인이 자동차를 운전하고 있다는 내용을 반환해야합니다.
'{자동차주인이름} can not do anything else
{자동차주인이름} is driving now.'
(hint)
첫 번째 문장은 CarOwner 클래스의 concentrate() 메소드를 사용해 구현하고,
두 번째 문장은 아래에서 구현하여 반환되도록 구현해보세요!
"""
return f"{self.owner.concentrate()}\n{self.owner.name} is driving now."
# 리턴값 print하면 줄바꿈 잘 보임. colab에서 함수 실행해봤을 때 안되서 왜인지 의아했었음.
class SelfDrivingCar(Car):
"""
문제 5.
이 자동차는 자율주행 자동차입니다!
자동차를 상속받아주세요!
"""
def drive(self):
"""
문제 6.
이 자동차는 자동차 주인이 있지만... 자동차 주인이 운전하지 않고 스스로 운전하네요!
drive 메소드를 통해
'Car is driving by itself'를 반환해야합니다.
상속을 받았는데.. drive메소드를 다시 선언해도 괜찮을까요?
메소드 오버라이딩 개념을 다시 생각해보며 코드를 작성해주세요.
"""
return 'Car is driving by itself'
# 메소드 오버라이딩은 말 그대로 부모 클래스에 있는 메서드에 덮어쓰는 것이다.
# 모듈을 import해서 쓰면 수정할 순 없고 그대로 써야하는데 그럴 때 쓸 수 있다고 하는듯?
class
에 대해서 이전에 점투파를 통해서 공부는 했지만 실제로 이렇게 뭘 만들어본게 처음이다 보니 굉장히 헷갈렸다.[part2]
class Computer:
"""
## Computer 클래스의 코드는 수정하지 마세요 ##
이미 완성된 코드입니다.
아래 코드를 활용하여 문제를 해결해주세요.
"""
def __init__(self, cpu, ram):
self.CPU = cpu
self.RAM = ram
def browse(self):
return('browse')
def work(self):
return('work')
class Laptop(Computer):
"""
위에 작성된 Computer 클래스를 상속받는 Laptop 클래스를 완성해주세요.
"""
def __init__(self, cpu, ram, battery):
"""
문제 1.
Laptop 클래스의 생성자 함수를 완성해주세요.
Laptop은 컴퓨터에 기본적으로 들어가는 부품 이외에 배터리도 추가됩니다.
Computer 클래스에서 사용하는 변수에 battery를 추가해주세요.
super키워드를 사용하여 상속받는 클래스에서 부모 클래스의 생성자를 사용하는 방법에 대해 익혀주세요.
"""
super().__init__(cpu, ram) # 상속
self.battery = battery # 변수 추가
'''
[기록]
부모 클래스에서 정의한 함수와 자식 클래스에서 정의한 함수 이름이 같은 경우,
부모 클래스의 함수를 호출하려면 두 가지 방법 중 하나를 사용해야 합니다.
1) 부모클래스명.함수명()
2) super().함수명()
즉, super()는 자식클래스에서 부모클래스에 있는 함수를 사용하고 싶고,
플러스 해당 함수명이 자식클래스에 중복되어 있을 때 사용할 수 있는 코드입니다.
'''
def oop_explain():
"""
문제 2. OOP에 대해서 공부하신 내용들을 최대한 많이 작성해주세요.
OOP의 구성에 대해서도 설명을 작성해주세요
"""
answer = """
OOP 개괄
- OOP는 프로그래밍 설계의 다양한 방법론 중 하나이다. (즉, 항상 옳은 절대선이 아니다)
- OOP의 기본 전제는 함수, 변수 등의 기능이 재사용 가능하도록 설계 및 프로그래밍 하는 것이다. (중요!!)
이해를 돕기 위해 절차적 프로그래밍(Procedural Programming)과 비교하자면,
=> 절차 지향 프로그래밍은 프로그래밍된 순서에 따라 순차적으로만 작동한다.
=> 반면 OOP는 현실에서 발생할 수 있는 object를 컴퓨터에 인식시키고, 이들 간의 상호작용을 통해 프로그래밍이 이루어진다.
=> 즉, 기존에 작성된 기능을 필요시 언제든지 불러와 재사용할 수 있어 코드를 간결하게 만들 수 있는 것이다.
=> 다만 그렇기 때문에 OOP는 여러 개체를 효율적으로 분리하는 것이 중요하며, 프로그래머가 어떻게 기능별 설계를 하는지에 따라 성능이 달라질 수 있다.
OOP 구성
- 캡슐화: class 내부에 객체의 공통된 속성과 행위를 변수와 함수로 정의하는 것을 말한다. (= 기능별로 분리해서 같은 기능끼리 하나로 묶자!)
=> 캡슐화는 OOP의 가장 중요한 기능 중 하나이며, 캡슐화를 통해 유저가 변수나 메서드에 직접 접근하여 실수로 데이터를 변경하는 행위를 방지해준다.
=>
- 상속(inheritance): 상속을 통해 부모 클래스(=상위 클래스)의 모든 기능을 그대로 받아와 사용할 수 있다.
=> 이때 부모 클래스에 있는 기능의 일부를 자식 클래스에서 변경하여 사용할 수 있다. 이를 다형성이라고도 한다. (예. 메서드 오버라이딩/오버로딩)
=> 자식 클래스에서는 부모 클래스에 없는 기능을 추가하여 사용할 수 있다. 단, 부모 클래스에서는 자식 클래스에 있는 추가된 기능을 사용할 수 없다. (자식 이기는 부모 없다!로 기억)
- 포함 (composition): 상속처럼 아예 부모 클래스의 기능을 가져오는 것이 아니라, 하나의 클래스에 다른 클래스의 일부 기능(함수)만을 가져와 사용하는 것을 말한다.
=> 오늘 과제 중 part1의 'Car' class에 쓰인 것이 그 예시이다.
- 추상화: 추상 클래스는 메서드의 목록만 가진 클래스이며, 상속받는 클래스에서 메서드 구현을 강제하기 위해 사용된다고 한다.
=> 추상 클래스로는 인스턴스를 생성할 수는 없고, 오로지 상속을 위해서만 사용된다.
=> 추상 클래스의 유용성에 대해선 너무 다양한 상황과 제약사항이 있다고 한다. 하나 기억할만한 건 '프로그램에 대한 요약과 표준화'이다.
=> 추상 클래스에 프로그램의 핵심적인 개념 또는 기능을 간추려 제공하고, 또 구현을 강제하기 때문이다.
# reference: https://continuous-development.tistory.com/71
"""
return answer
super()
를 쓰고 언제 부모클래스명.함수명()
을 쓰는지 잘 기억해두자.OOP
에 대해서는 나중에 공부노트로 제대로 정리해봐야겠다. (언제 가능하려나..)