본문 바로가기

나 취준생/파이썬

클래스 생성자, self, 상속, 클래스 변수와 인스턴스 변수 차이점

320x100

# 클래스를 사용해서 파이썬 코딩을 해야하는 이유?


- 객체 지향 언어의 장점인 상속을 활용할 수 있기 때문


ex) 신용카드 발급 및 사용 프로그램 구축


팀장님 --> 카드의 중요 기본 기능을 담는 클래스(설계도) 생성

               클래스 이름 : Card()

        

나      --> 영화 할인 카드 클래스 생성

팀원   --> 주유 할인 카드 클래스 생성


만약 내가 팀장님이 만든 카드의 중요 기능(메소드)을 담은 클래스(Card)를

상속받기만 하면 나는 팀장님이 코딩한 카드의 주요 기능을 코딩하지 않아도 되고

나는 단순히 영화 할인에만 집중해서 코드를 구현하기만 하면 된다.



# 카드의 기능 ?


1. 충전

2. 소비


이에 따른 카드 클래스 만들기


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class card():
    def __init__(self):
        self.cash=0
        print('카드가 발급되었습니다')
    def charge(self,num):
        self.cash+=num
        print(num,'원이 충전되었습니다')
    def consume(self,num):
        if self.cash>=num:
            cash-=num
            print(num,'원이 사용되었습니다')
        else:
            print('잔액이 부족합니다')
koo_card=Card()
lee_card=Card()
koo_card.charge(10000)
lee_card.consume(1000)
koo_card.consume(1000)
cs



# 클래스 생성자 __init__(self)


클래스의 인스턴스 객체가 생성될 때자동적으로 호출되는 메소드가 클래스 생성자이다.


위의 경우 - koo_card=card()로, 객체가 생성되자마자 자동으로 '카드가 발급되었습니다'라고 출력되었다.


# self


또한 

charge(self,num)의 self는 객체 자신을 의미하는 것으로, 이후에 디폴트 값이 된다.

따라서 num에는 10000이 들어갔을때,

self에는 koo_card 가 암시적으로 들어갔기 때문에

그래서 lee의 카드가 아닌 koo의 카드에만 돈이 충전되었다.


1
2
3
4
5
6
7
8
9
10
class Gun():
    def __init__(self):
        self.bullet=0
        print('총이 만들어졌습니다')
    
    def __del__(self):
        print('총이 폐기 되었습니다')
        
koo_gun=Gun()
del koo_gun




또한 __init__(self) 와 반대로, 객체가 사라질 때 자동으로 호출되는 함수를 소멸자 (__del__) 라고 한다.


총 클래스로 koo_gun이라는 총을 만들고 사용하다가

이제 총을 폐기하고 싶으면 del 명령어로 총을 폐기하면 되는데

이 때 자동으로 작동되는 메소드가 소멸자 함수이다.





# 클래스 상속 이해하기


클래스는 상속이라는 특성을 가지고 있는 이름 공간이다.

클래스에서 상속이란 어떤 클래스가 갖고 있는 멤버(변수)나 메소드(함수)를

상속받는 클래스가 모두 사용할 수 있도록 해주는 것


상속을 해주는 클래스를 부모 클래스 또는 슈퍼 클래스라 하고

상속을 받는 클래스를 자식 클래스 또는 서브 클래스라고 한다.

부모 클래스로부터 상속을 받아 자식 클래스를 정의하는 방법은 다음과 같다.


자식 클래스는 부모 클래스에서 정의된 모든 멤버와 메소드를 그대로 상속받는다.


1. 팀장님이 카드의 주요 기능을 담고 있는 Card() 클래스를 생성

2. 팀원인 나는 카드 클래스를 만들 것인데

팀장님이 구현한 카드의 주요 기능을 Card()로부터 다 상속받고

나는 팀장님이 구현한 코드는 구현하지 않는다.

나는 그저 영화 할인에만 집중해서 메소드를 만들면 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# 부모 클래스
class Card:
    def __init__(self):
        self.cash=0
        print('카드가 발급되었습니다')
    def charge(self,num):
        self.cash+=num
        print(num,'원이 충전되었습니다')
    def consume(self,num):
        if self.cash>=num:
            self.cash-=num
            print(num,'원이 사용되었습니다')
        else:
            print('잔액이 부족합니다')
# 자식 클래스
class Movie_Card(Card):
    def consume(self,num,place): # 오버라이딩(덮어쓰기)
        if place in ('영화관','주유소'):
            num=0.8*num
            if self.cash>=num:
                self.cash-=num
                print(place,'에서',num,'원이 사용되었습니다.')
            else:
                print('잔액이 부족합니다')
        elif place=='스타벅스':
            num*=0.9
            if self.cash>=num:
                self.cash-=num
                print(place,'에서',num,'원이 사용되었습니다.')
            else:
                print('잔액이 부족합니다')
        else:
            if self.cash>=num:
                self.cash-=num
                print(num,'원이 사용되었습니다')
            else:
                print('잔액이 부족합니다')
m_card1=Movie_Card()
m_card1.charge(100000)
m_card1.consume(200000,'집')
m_card1.consume(10000,'편의점')
m_card1.consume(10000,'영화관')
m_card1.consume(10000,'주유소')
m_card1.consume(10000,'스타벅스')




부모 클래스에 consume()이라는 메소드가 있지만,

상속받은 자식 클래스에 consume()이라는 메소드를 매개변수를 다르게 해서 다른 함수처럼 사용할 수 있다.

이것을 오버라이딩이라 한다.




# 클래스 변수와 인스턴스 변수의 차이


1. 월급 상승율인 raise_amount에 인스턴스 변수 사용


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
"""
사원이 입사하면 입사한 사원에 대한 이메일을 자동으로 생성하고
이름을 출력하는 함수와 월급을 인상하는 함수를 담는 클래스 생성
"""
 
class  Employees:
    raise_amount = 1.1  # 클래스 변수
    def __init__(self, first, last, pay): # 객체가 만들어질때
        self.first = first               # 바로 작동되는 함수
        self.last  = last
        self.pay   = pay
        self.email = first.lower() + '.' + last.lower() + '@gmail.com'
        self.raise_amount = 1.1  # 인스턴스 변수
 
    def  full_name(self): #사원의 전체이름을 출력하는 함수
        print ('{} {}'.format(self.first, self.last))
 
    def  apply_raise(self): # 월급을 인상하는 함수
        self.pay = intself.pay * self.raise_amount)
 
 
emp_chulsu = Employees('chulsu''kim'5000000)
print(emp_chulsu.pay)   # 5000000가 출력됨
print(emp_chulsu.email)
emp_chulsu.apply_raise()
print(emp_chulsu.pay)  # 5500000가 출력됨
 
emp_chulsu2 = Employees('chulsu2''kim'5000000)
emp_chulsu2.raise_amount = 1.2          # 철수가 클래스 밖에서 raise_amount를 1.2로 조작
print(emp_chulsu2.pay)   # 5000000
emp_chulsu2.apply_raise()
print(emp_chulsu2.pay)  # 6000000       # 철수만 월급이 1.2배가 되었다.
cs

 

2. 월급 상승율인 raise_amount에 클래스 변수 사용


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class  Employees:
    raise_amount = 1.1  # 클래스 변수
    def __init__(self, first, last, pay): # 객체가 만들어질때
        self.first = first               # 바로 작동되는 함수
        self.last  = last
        self.pay   = pay
        self.email = first.lower() + '.' + last.lower() + '@gmail.com'
        self.raise_amount = 1.1  # 인스턴스 변수
 
    def  full_name(self): #사원의 전체이름을 출력하는 함수
        return  '{} {}'.format(self.first, self.last)
 
    def  apply_raise(self): # 월급을 인상하는 함수
        self.pay = intself.pay * Employees.raise_amount)  # 이번에는 self가 아닌, 클래스 변수를 사용 
 
 
emp_chulsu2 = Employees('chulsu2''kim'5000000)
 
emp_chulsu2.raise_amount = 1.2   # 인스턴스 변수만 변경할 수 있고 클래스 변수는
                                             # 변경할 수 없다. 
 
print(emp_chulsu2.pay)   # 5000000
emp_chulsu2.apply_raise()
print(emp_chulsu2.pay)  # 6000000   # 조작 실패
 
# 클래스 변수 : 메소드 바깥의 변수 ( 객체 생성 이후 값 변경 불가 )
 
# 인스턴스 변수 : 메소드 내의 변수
 
# 위와 같이 민감한 변수들은 인스턴스 변수가 아닌 클래스 변수를 사용해서 코딩해야한다.
cs


반응형