DevSSOM
파이썬 기초 - 객체지향 프로그래밍 본문
객체
: 성질과 할 수 있는 행동을 담은 자료. 지금까지 우리가 배워온 걸로는 성질은 주로 변수, 할 수 있는 행동은 주로 함수로 얘기되어 왔는데, 이 둘을 하나로 합친 자료인 객체라는 애를 만들어냄. 예를 들어서, 객체를 어피치라고 하면
[성질]
이름 : 어피치
나이 : 10대 후반 ~ 20대 초반
성별 : 자웅동체
[할 수 있는 행동]
춤추기
울기
웃기
클래스(Class)
: 객체를 만들 수 있는 틀. 이모티콘이라면 말이야... 이름, 나이, 성별(성질)이 있어야 하고 엉덩이 흔들기, 모르는척 하기, 땡강부리기(행동)을 할 줄 알아야 돼. 그래서 이 객체를 찍어내는 클래스를 만들기 위해서
class 클래스이름: 으로 생성.
class Emoticon
클래스 안에는 성질과 행동을 담아줘야 하니까
필드(Field)
: 객체가 가지고 있는 성질 = 객체가 가지고 있는 변수.
class Emoticon:
name = "Apeach"
age = 20 # 10대후반 ~ 20대초반을 평균내서
이렇게 두개의 변수를 추가하게 되면, Emoticon은 두 가지 성질을 가지게 돼. name과 age라는 성질. 이렇게 클래스 안에 변수를 정의해줌으로써 필드를 만들 수 있어.
메소드(Method)
: 객체가 할 수 있는 행동 = 객체가 할 수 있는 함수. 이전에 메소드를 짝꿍이 있는 함수라고 했는데, 이 짝꿍이 바로 객체야. 그래서 객체 안에 들어있는 함수를 메소드라고 함.
class Emoticon:
def dance(self):
print("Booty Shake!")
댄스라고 하는 함수를 정의한 뒤, 프린트 엉덩이 흔들기라고 하면, 이모티콘이라고 하는 클래스 안에는 댄스라고 하는 메소드가 생긴거야. 그리고 이 메소드는 이모티콘이 할 수 있는 행동을 의미하게 돼. 이렇게 객체 안에 함수를 정의하게 되면 객체가 할 수 있는 행동을 정의하게 되고, 그게 곧 메소드라는 것.
- Self : 메소드라면 가져야하는 첫번째 매개변수. 파이썬에서 메소드를 정의할 때 쓰는 하나의 규약이야. 메소드임을 나타내주기 위해서는 함수를 정의하고 매개변수 안에 셀프를 넣어주는거야.
이제 이 클래스에서 찍어낸 객체가 궁금해. 걔를 인스턴스라고 하는거야.
인스턴스(Instance)
: 객체를 만들 수 있는 틀(Class)로 찍어낸 객체. 인스턴스를 만들 땐, 인스턴스 이름 = 클래스 이름()
apeach = Emoticon() # 이모티콘 클래스에서 인스턴스 어피치를 찍어내겠다
이모티콘이라는 클래스로 만든 어떤 객체 어피치는 어피치라는 이름과 20살 나이라는 성질 그리고 엉덩이 춤을 출 수 있고, 웃고 울 수 있는 행동을 가지게 돼. 이모티콘이라는 클래스로 어피치 인스턴스를 만드는거야. 그래서 클래스와 인스턴스의 관계는 붕어빵 틀(클래스)과 팥붕어빵, 슈붕어빵(인스턴스)의 관계와 같아. 같은 틀로 팥붕어빵이 나오고 슈붕어빵이 나올 수 있는 것처럼 인스턴스마다 저마다의 특징이 조금씩은 달라질 수 있지만, 그럼에도 여전히 붕어빵 클래스인점은 달라지지 않아.
인스턴스의 변수(필드)는 인스턴스.필드
appeach = Emoticon()
apeach.name # apeach
apeach.age # 20
인스턴스의 함수(메소드)는 인스턴스.메소드()
apeach = emoticon()
apeach.dance() # 엉덩이 춤추기!
# 에어컨이 가져야 할 속성 : 희망온도, 바람속도, ...
# 에어컨이 할 수 있는 행동 : 온도 높이기/낮추기, 바람속도 조절, ...
class Aircon: # Aircon 클래스를 생성
temp = 20 # 희망온도 변수
wind_speed = 1 # 바람속도 변수
def wind_speed_up(self): # 바람속도를 증가시키는 함수
self.wind_speed = self.wind_speed + 1
crystal = Aircon() # Aircon의 성질을 가진 객체 crystal 생성
print(crystal.temp) # 20
print(crystal.wind_speed) # 1
crystal.wind_speed_up() # 메서드 호출
print(crystal.wind_speed) # 2
객체지향 프로그래밍
Q) 왜 객체지향 프로그래밍인가?
: 상속, 다형성, 캡슐화를 통해 코드의 재사용이 쉽고, 우리 실생활을 더 잘 나타낼 수 있기 때문에.
상속
: 한 클래스의 내용을 다른 클래스가 이어받는 것.
상속을 통해 한 클래스에서 다른 클래스로 핵심 정보를 전달해줄 수 있어. 기존 코드를 재활용하는거지.
class Car:
type = "자동차"
class Hyundai(Car): # 괄호 안에는 상속받을 클래스의 이름을 적어줘
pass # 클래스 안에는 아무것도 안적어줄거야
sonata = Hyundai() # 소나타라고 하는 인스턴스는 현대라고 하는 클래스를 이어받았어
print(sonata.type) # 현대라고 하는 클래스에 아무것도 입력하지 않았는데,
# 소나타라고 하는 타입을 이어받은걸 볼 수 있어
# 이건 카라고 하는 클래스에서 타입을 정해줬는데,
# 현대라고 하는 클래스에서 카를 상속받았기 때문에
class Tree:
height = 0
leaf_size = 0
...
class CherryBlossom(Tree): # Tree의 성질을 그대로 계승!
height = 25 # 벚꽂나무에 맞게 값을 재조정
leaf_size = 1
# 마치 부모와 자식처럼 코드를 관리 가능
# 현실 세계의 객체 구조와 유사
다형성
: 같은 모양의 코드가 다른 역할을 하는 것. 그래서 코드를 더 간단하게 만들 수 있어.
class Car:
type = "자동차"
horsePower = 100
class Lamborghini(Car):
horsePower = 700
aventador = Lamborghini()
print(aventador.type) # 자동차
print(aventador.horsePower) # 700
ford = Car()
print(ford.type) # 자동차
print(ford.horsePower) # 100
# 이렇게 같은 horsePower임에도 불구하고 어떤 객체냐, 어떤 클래스냐에 따라 값이 달라지게 돼
class CherryBlossom(Tree):
height = 25
leaf_size = 1
class Mugunghwa(Tree):
height = 1
leaf_size = 5
# 같은 height, leaf_size 변수가 있지만
# class마다 가지는 값이 다르다!
# 같은 이름으로 각 객체의 값을 관리할 수 있음
class Animal:
legs = 0
def walk(self):
return ""
class Dog(Animal):
legs = 4
def walk(self):
return "살랑살랑"
class Human(Animal):
legs = 2
def walk(self):
return "뚜벅뚜벅"
maltese = Dog()
gildong = Human()
print(maltese.walk()) # 살랑살랑
print(gildong.walk()) # 뚜벅뚜벅 # 같은 walk 메소드라고 해도 어떤 클래스였냐에 따라 출력이 달라
캡슐화
: 보기 쉽게 코드를 묶어서 정리할 수 있음. 정보 은닉해서 사적인 정보들을 잘 숨길 수도 있어.
Q) 객체지향 프로그래밍으로 하면 뭐가 다른가?
ex) 포켓몬 게임에서 치코리타가 구구에게 '울음소리' 기술로 10의 데미지를 입혔다 -> 이걸 우리가 지금까지 배운 내용으로 구현할 수 있을까? No. 하지만 이런 상황에서 객체지향 프로그래밍을 사용한다면 문제를 조금 더 쉽게 해결할 수 있어.
포켓몬 클래스 생성
- 포켓몬이라면 가져야할 특징은? 이름, 체력, 타입 등
- 포켓몬이라면 할 수 있는 능력은? 각 포켓몬의 기술
이렇게 포켓몬을 필드와 행동으로 나눠서 생각할 수 있으니까 아래와 같이 클래스를 정의할 수 있어
class Pocketmon:
p_name = ""
p_hp = 0
p_type = ""
def skill(self):
pass
피카츄 클래스를 생성해보면, (포켓몬 클래스를 상속하는 피카츄 클래스 생성)
- 피카츄의 특징은? 이름 피카츄, 성비 5:5, 체력은 50이고, 전기 속성이다
- 피카츄의 능력은? 백만 볼트
class Pikachu(Pocketmon):
p_name = "Pikachu"
p_hp = 50
p_type = "Electric"
def skill(self):
print("백만 볼트!")
피카츄 인스턴스 생성
피카츄 클래스로 찍어 낸 pika 인스턴스
pika = Pikachu()
pika.skill() # 백만 볼트!
print(pika.p_hp) # 50
파이썬에서의 객체
파이썬에서는 객체 단위로 정보를 관리함. 숫자형자료 1 2 3, 문자열자료 'abc', 리스트 자료 [1, 2, 3] 얘네 하나하나가 모두가 객체에 해당. 이들의 자료형이었던 int, str, list 등등은 이 자료형의 클래스야. 그리고 이들이 객체이기 때문에, 다음과 같은 속성을 가지고 있음.
- 값(Value) : 객체에 담긴 내용
- 유형(Type) : 객체의 종류
nums = [1, 2, 3]
print(nums) # [1, 2, 3] 이게 객체의 값
print(type(nums)) # <class 'list'> nums의 클래스는 리스트
# 리스트가 객체니까 이 리스트에 딸려있는 함수, 즉 메소드를 쓸 수 있어
# 우리가 리스트나 숫자나 딕셔너리에 메소드를 사용할 수 있었던 이유가
# 파이썬이 자료를 객체로 저장하기 때문이야
# 그래서 객체들 = 자료들은 값과 유형을 가지고 있다는 것
nums.append(4)
print(nums) # [1, 2, 3, 4]
연습문제
# 클래스 Bbread(붕어빵)을 만들어봅시다.
# Bbread의 필드 taste를 생성하고, "밀가루"를 대입해봅시다.
# Bbread의 메서드 eat()를 생성해봅시다. 이 메서드는 taste, "맛이 나요!"를 출력합니다.
# taste의 값이 "밀가루"라면 "밀가루 맛이 나요!" 가 출력됩니다.
class Bbread:
taste = "밀가루"
def eat(self):
print(self.taste, "맛이 나요!")
# 클래스 Bbread의 인스턴스 redBean과 choux를 만들어봅시다.
redBean = Bbread()
choux = Bbread()
# 객체 redBean의 필드 taste를 "팥"으로 바꿔줍시다
redBean.taste = "팥"
# 객체 choux의 필드 taste를 "슈크림"으로 바꿔줍시다
choux.taste = "슈크림"
# 객체 redBean의 메서드 eat()를 실행해봅시다
redBean.eat() # 팥 맛이 나요!
# 객체 choux의 메서드 eat()를 실행해봅시다
choux.eat() # 슈크림 맛이 나요!
'Python > 기초' 카테고리의 다른 글
파이썬 Numpy - 배열의 인덱싱과 슬라이싱 (0) | 2021.07.26 |
---|---|
파이썬 Numpy - 배열의 기초 (0) | 2021.07.26 |
파이썬 Numpy - 개념 (0) | 2021.07.24 |
파이썬 기초 - 반복문 (for문, for-range문, while문, break문) (0) | 2021.06.09 |
파이썬 기초 - 시퀀스 자료형 (0) | 2021.06.09 |
파이썬 기초 - 리스트 활용2 (0) | 2021.06.09 |
파이썬 기초 - 조건문 (if - elif - else) (0) | 2021.06.09 |