1. 클래스 & 인스턴스
class (=클래스 =설계서) : '부류' ---------- PART A
instance (=인스턴스 =제품) : '실체' ---------- PART B
object (=오브젝트 =객체) : 모든 '실체'를 대표하는 포괄적인 의미를 갖는다.
• 클래스의 인스턴스는 객체다.
• 실제 세계에 존재하는 인스턴스를 '객체'라고 하는 것.
• 객체들의 공통점을 간추려서 개념적으로 먼저 나타내주는 게 '클래스'
예시1
클래스 | 가수 | '가수'라는 단 하나의 사람 or 물건이 실제 존재하지 않는다. 노래하는 사람을 '가수'라고 말함. |
객체 | 영지 | '가수'라는 클래스를 이용해 실체를 만들 수 있다. '영지'라는 객체가 만들어졌다. |
객체 | 폴킴 | '가수'라는 클래스를 이용해 실체를 만들 수 있다. '폴킴'이라는 객체가 만들어졌다. |
예시2
클래스 | 포켓몬 | '포켓몬'이라는 단 하나의 실체가 실제 존재하지 않는다. 포켓몬들을 통틀어 '포켓몬'이라고 말함. |
객체 | 피카츄 | |
객체 | 뮤 |
2. 속성 & 메서드
attribute (=속성 =변수) : 해당 클래스로 생성된 객체들이 갖는 '공통적인' 특성? 특징? 정의
method (=메서드 =기능) : 해당 클래스로 생성된 객체들이 할수있는 행동? 기능? 정의
- 클래스가 갖는 속성(변수) / 객체가 갖는 속성(변수) -> 둘을 항상 구분해서 생각해야한다
- def example(self)
: 클래스 내에서 메서드 정의시 'self'라는 인자를 받지만, 객체 생성후 객체의 메서드 호출할 때는 인자를 써주지 않아도, 객체 스스로가 첫번째 인자로 전달된다. 'self' 라는 것은 바로 그 클래스의 객체를 가리키는데, 예를 들어 영지와 폴킴이 클래스 내에 정의된 sing(노래하기) 메서드를 똑같이 가지기 때문에 서로 구별하기 위해서 사용한 것. 우리는 객체를 더 만들 수 있고 만들어진 객체들은 서로 구별되어야 하기 때문에.
- def __init__(self)
: 파이썬에서 특별하게 약속된 메서드 가운데 하나인, 초기화(initialize) 메서드. 어떤 클래스의 객체를 생성할 때 자동으로 처음에 호출되는 특수한 메서드로, 그 '객체'가 갖게 될 여러가지 성질(= 속성, 변수)를 미리 정해두는 것. 반드시 첫 번째 인수로 self를 지정해야하고, 다른 인수를 받고 싶다면 self 다음에 이어서 적어주면 된다. 왜 객체의 성질을 미리 정해주는게 좋느냐? CODE로 보기 (2)으로!
[예시1] | [예시2] | [예시3] | [예시4] | |
클래스 | 가수 | 포켓몬 | 사람 | 학생 |
객체 | 영지 | 피카츄 | Alice | Chris |
객체 | 폴킴 | 뮤 | Ben | Diana |
속성 | 음정 | 파워 | 눈 | 키 |
속성 | 박자 | HP | 입 | 몸무게 |
메서드 | 노래하기 | 훈련하기 | 밥먹기 | 공부하기 |
메서드 | 연습하기 | 진화하기 | 얘기하기 | 발표하기 |
1) 실행 단계
PART A
-> 클래스를 정의하고, 해당 클래스의 성질이나 행동을 정의하는 파트
step1
클래스를 정의한다. = 클래스를 만든다
class '클래스 이름'
step 2
해당 클래스의 성질이나 행동을 정의한다.
'변수 이름' = 값 -> 클래스가 갖는 공통 성질을 정의 (클래스의 특징)
def __init___(self) -> 객체가 갖는 성질을 초기화 메서드로 미리 정의 (객체의 특징)
def '메서드 이름'(self) -> 클래스가 하는 행동을 정의 (기능)
step 3
미리 정의해둔 클래스를 상속받는 새로운 클래스를 정의한다.
class '새로운 클래스 이름' ('미리 정의해둔 가져올 클래스 이름')
PART B
-> 정의된 클래스를 이용하여 인스턴스를 생성하고, 생성된 인스턴스의 성질이나 행동 실행하는 파트
step 4
클래스를 이용하여 인스턴스를 생성한다.
'객체 이름' = '클래스 이름'( )
step 5
생성된 인스턴스에게 미리 정의해둔 속성, 메서드를 실행시켜 본다.
'객체이름'.'변수 이름'
'객체 이름'.'메서드이름'( )
- 클래스로 만든 모든 객체들은, 클래스 안에 정의된 모든 메서드 사용할 수 있다.
- 클래스로 만든 모든 객체들은, 클래스 안에 정의된 모든 특성을 공통적으로 갖는다.
2) CODE로 보기 (self & __init__ 개념)
Singer 라는 클래스 안에 클래스 변수(성질) tone, beat 와 메서드(기능) sing 을 미리 정의해놓는다.
그 다음 Singer 라는 클래스를 통해 youngji라는 객체를 생성하면, youngji는 Singer라는 클래스를 이용해 만들었기 때문에 Singer 라는 클래스 안에 정의해둔 '성질'을 가질 수 있고, '기능'도 모두 실행할 수 있게 된다. 따라서 youngji에게 sing(노래하기) 메서드를 실행시킬 수 있다.
PART A
class Singer: # 1단계 Singer 클래스 정의
tone = 90 # 2단계 Singer 클래스 안에서 tune(음정) 특징 정의
beat = 90 # 2단계 Singer 클래스 안에서 beat(박자) 특징 정의
def sing(self): # 2단계 Singer 클래스 안에서 sing(노래하기) 메서드 정의
return "yeah~~~"
def practice(self): # 2단계 Singer 클래스 안에서 practice(연습하기) 메서드 정의
self.tone += 2
self.beat += 1
def __init__(self): # 2단계 Singer 클래스 안에서 초기화 메서드 정의
print("새로운 가수가 데뷔했습니다!")
PART B
첫번째 객체 생성(youngji) -> 객체가 생성되면서 초기화 함수가 자동으로 실행된 것을 확인할 수 있다.
youngji = Singer() # Part2_1단계 youngji 라는 이름의 객체 생성
# 새로운 가수가 데뷔했습니다!
youngji.beat # Part2_2단계 youngji 라는 이름의 객체가 갖는 beat(박자) 변수 실행
# 90
youngji.sing() # Part2_2단계 youngji 라는 이름의 객체에 sing(노래하기) 메서드 실행
# 'yeah~~~'
두번째 객체 생성(paulkim) -> 객체가 생성되면서 초기화 함수가 자동으로 실행된 것을 확인할 수 있다.
연습하기 메서드를 실행하고 음정 변수를 호출하면 '92' 로 출력된 것을 확인할 수 있다.
paulkim = Singer() # Part2_1단계 paulkim 이라는 이름의 객체 생성
# 새로운 가수가 데뷔했습니다!
paulkim.practice() # Part2_2단계 paulkim 이라는 이름의 객체에 practice(연습하기) 메서드 실행
paulkim.tone # Part2_2단계 paulkim 이라는 이름의 객체의 tone(음정) 속성 호출
# 92
3) CODE로 보기 (self & __init__)
포켓몬 라는 클래스 안에 공통적으로 갖는 클래스 변수(성질)이 아닌 각 객체마다 다르게 가질 인스턴스 변수(성질)을 정의할 수 있다. inputspec 메서드에서 파워, hp, 레벨 인자를 받아서 가질 수 있게 정의해둔다. 정의가 끝나면 먼저 'pikachu' 객체를 생성하고나서, inputspec 메서드를 실행하여 피카츄의 스펙을 입력할 수 있다.
PART A
class Pokemon:
def inputspec(self, power, hp, level):
self.power = power
self.hp = hp
self.level = level
def training(self):
self.power += 10
self.hp += 5
print("power: " self.power ", hp: " self.hp)
def levelup(self):
self.power *= 2
self.hp *= 2
self.level += 1
print("진화 성공 레벨업! level: " self.level)
PART B
pikachu = Pokemon() # Part2_1단계 pikachu 라는 이름의 객체 생성
pikachu.inputspec(60, 70, 2) # Part2_2단계 pikachu 객체에 inputspec 메서드 실행하여, 스펙을 입력 받음.
pikachu.training()
# power: 70, hp: 75
pikachu.levelup()
# 진화 성공 레벨업! level: 3
위에서 처럼 피카츄 라는 객체를 생성만 하고 아무것도 하지 않으면, 피카츄는 파워/힘/레벨 이런 성질들을 아무것도 갖지 못한 상태인 것이다. 즉 inputspec 메서드를 실행해주지 않으면 training 이나 levelup 같은 미리 정의해둔 다른 메서드들도 모두 사용할수가 없다. 그냥 인형.... 꼭 inputspec 메서드를 실행해주어야만 피카츄는 성질을 갖게되고, training 이나 levelup 메서드도 사용할 수 있는 것이다.
그래서 바로 여기서 __init__이 필요한 이유가 나온다.
객체가 생성되자마자 바로 초기값으로 스펙을 갖게되면 굳이 inputspec 메서드를 실행해주지 않아도, training 이나 levelup 과 같은 메서드를 실행해줄 수 있기 때문에 편하다. 단순히 편함 뿐만아니라 굳이 꼭 처음에 무언가를 수행해주어야 하는 과정이 있으면 나중에 실행할때 그걸 누락하여 오류가 발생되는 상황이 생길 수도 있지만, 초기값을 설정하게 되면 그런 상황이 안생기게 되니까 보다 안전하다.
이제 위 코드에 있었던 inputspec 대신, 객체를 생성하자마자 성질을 갖도록 __init__(초기화메서드)를 정의해보자.
PART A
방법1 (inputspec 없애고 __init__ 안에 inputspec에 있던 내용 모두 다시 적어주기)
class Pokemon:
def __init__(self, power, hp, level):
self.power = power
self.hp = hp
self.level = level
def training(self):
self.power += 10
self.hp += 5
print("power: " self.power ", hp: " self.hp)
def levelup(self):
self.power *= 2
self.hp *= 2
self.level += 1
print("진화 성공 레벨업! level: " self.level)
방법2 (inputspec 살리고 __init__ 안에 inputspec 그대로 적어주기)
class Pokemon:
def inputspec(self, power, hp, level):
self.power = power
self.hp = hp
self.level = level
def training(self):
self.power += 10
self.hp += 5
print("power: " self.power ", hp: " self.hp)
def levelup(self):
self.power *= 2
self.hp *= 2
self.level += 1
print("진화 성공 레벨업! level: " self.level)
def __init__(self, power, hp, level):
self.inputspec(power, hp, level)
객체를 생성시키면서 힘, hp, 레벨을 인자로 받아서, inputspec 메서드에게 넘겨주도록 했다(방법2). 물론 초기화 메서드에서 직접 변수를 다뤄도(방법1) 상관없지만 이왕 inputspec 메서드를 미리 만들어뒀으니까 이용을 한 것! 이제부터는 객체를 만들 때는 다음과 같이 세 개의 인자를 반드시 넘겨줘야한다.
PART B
eevee = Pokemon(40, 50, 1) # Part2_1단계 eevee 라는 이름의 객체 생성되면서, 스펙 인자값들 받으며 갖게됨.
eevee.training() # Part2_2단계 eevee 객체에 트레이닝 메서드 실행
# power: 50, hp: 55
eevee.levelup()
# 진화 성공 레벨업! level: 2
3) CODE로 보기 (self & __init__)
__init__ 인자를 받을수도 있지만, 값을 미리 정해줄 수도 있다.
master 는 무조건 지우라고 정하려면, 메서드 정의할 때 먼저 적어준다.
PART A
class Pokemon:
def inputspec(self, power, hp, level):
self.power = power
self.hp = hp
self.level = level
def training(self):
self.power += 10
self.hp += 5
print("power: " self.power ", hp: " self.hp)
def levelup(self):
self.power *= 2
self.hp *= 2
self.level += 1
print("진화 성공 레벨업! level: " self.level)
def __init__(self, power, hp, level, master='jiwoo'):
self.inputspec(power, hp, level)
self.master = master
PART B
pidgeot = Pokemon(70, 80, 2) # Part2_1단계 피존투 라는 이름의 객체 생성되면서, 스펙 인자값들 받으며 갖게됨.
print(pidgeot.master)
# jiwoo
3. 상속 (Inthritance)
: 어떤 클래스가 다른 클래스의 성질을 물려받는 것. 어떤 클래스를 만들 때 처음부터 모든 것을 새로 만들 필요 없이, 핵심적인 성질을 갖고 있는 다른 클래스로부터 상속을 받아서 조그만 손을 보면 쓸만한 클래스를 만들 수 있다.
1) CODE로 보기
PART A
class Person:
# 눈 두 개, 입 하나...
eyes = 2
mouth = 1
# 먹고 이야기하고...
def eat(self):
print 'yammy~'
def talk(self):
print 'blah~'
먼저, 보통사람을 나타낸 Person 이라는 클래스를 정의했다.
ㄴ 눈/입 속성을 정의했고, 밥먹기/얘기하기 메서드를 정의했다.
class Student(Person): # Person 클래스를 상속받은 'Student' 라는 클래스를 정의
def study(self):
print 'go go!'
이제, Student 라는 클래스를 만들건데, 학생도 사람이니까 Person의 눈/입 이런 속성을 갖고 있을 것이고, 밥먹기/얘기하기 같은 행동(메서드)을 당연히 할 수 있을 것이다. 거기에 Student만 갖는 특징적인 속성이나 메서드를 추가적으로 갖도록 하면 되는 것이다. 이 때 Student 클래스 안에 눈/입 속성, 밥먹기/얘기하기 메서드까지 모든 것을 새로 정의해주려면 너무 비효율적이라는 것이다.
이럴 때 '상속'을 이용하여 Student 클래스를 만들면 된다.
Student 클래스 안에 굳이 눈/입 속성이나 밥먹기/얘기하기 메서드를 굳이 하나하나 새로 만들어주지 않아도 Person의 속성과 메서드를 모두 물려받아서 갖게되는것이다.
❓ 상속받지 말고 그냥 위에 정의해둔 내용 복붙해서, 그대로 Student 클래스 안에 써주면 그렇게 귀찮지 않다고 생각할 수 있지 않을까? 물론 그렇게도 가능하지만, 나중에 속성이나 메서드를 수정하거나 추가해야하는 상황이 생기면 그럴 때마다 Person 클래스와 Student 클래스 모두 각각 수정이 필요해진다. 하지만 상속을 받으면 각각 수정해야 하는 상황이 생기지 않는다.
PART B
alice = Person() # Person 클래스로 생성된 객체 'alice'
alice.mouth
# 1
alice.talk()
# blah~
chris = Student() # Student 클래스로 생성된 객체 'chris'
chris.mouth
# 1
chris.talk()
# blah~
Student 클래스의 객체인 chris 도 Person 클래스의 객체인 alice 처럼 눈/입 속성을 갖고 밥먹기/얘기하기 행동을 한다. 왜냐면 Student 클래스가 Person 클래스를 상속받아 정의된 클래스이므로!
chris.study()
# go go!
추가적으로 chris는 Student 클래스의 객체이므로, Student 클래스 만의 메서드인 'study'라는 행동을 추가적으로 할 수 있다.
[참고자료]
'코드스테이츠 AI 부트캠프 > Section 3' 카테고리의 다른 글
[비공개] AIB_314_복습정리 : DB API (0) | 2021.12.27 |
---|---|
AIB_313_복습정리 : 트랜잭션 (0) | 2021.12.27 |
AIB_312_복습정리 : SQL (0) | 2021.12.27 |
AIB_311_복습정리 : 환경 세팅하기 (0) | 2021.12.27 |