본문 바로가기

Python

17. 클래스와 상속

1. 클래스 선언

'''
#      절차 지향 VS 객체 지향 (OOP : Object-Oriented Programming )
언어       C        JAVA, C#


# 클래스 = 설계도 
    : 속성 (데이터 변수)
    : 메소드 (기능=함수)


# 클래스 정의
class 클래스명 : 
    명령어

클래스명은 첫글자를 대문자로 정의
클래스안에 정의되는 속성과 메소드는 소문자로 정의
'''
# 사각형 클래스
# 속성 : 가로, 세로, 색상
# 기능 : 넓이구하기, 속성 출력하기 

# 클래스 선언
class Square:
    # 속성 정의 ==> 생성자 메소드(__init__(self))
    # self 는 기본 매개변수 
    def __init__(self, width, height, color):
        self.width = width # self 뒤의 width와 (=) 뒤의 width 는 달라도 됨. 앞은 속성 뒤는 매개변수
        self.height = height 
        self.color = color
    # 사각형의 넓이를 구하는 메소드 정의
    def print_area(self):
        print(f'{self.width}X{self.height} = {self.width*self.height}')
    # 사각형의 정보를 축력하는 메소드 정의
    def print_info(self):
        print(f' 사각형의 색상 : {self.color}')
        print(f' 사각형의 가로 : {self.width}')
        print(f' 사각형의 세로 : {self.height}')
        
# 객체화 = 인스턴스화
# 객체명(소문자) = 클래스명(속성값1, 속성값2 ....)
square1 = Square(12, 12, 'red')
square2 = Square(10, 20, 'blue')
# 속성 읽기 => 객체명.속성
print(square1)
# <__main__.Square object at 0x000002610E2BB410>
print(square1.color, square1.height, square1.width )
# red 12 12
print(square2)
# <__main__.Square object at 0x000002610E2BB440>
print(square2.color, square2.height, square2.width )
# blue 20 10

print(Square) # <class '__main__.Square'>  ==> 사용자 정의 타입

print(f'square1 객체의 넓이는? {square1.height*square1.width}')
print(f'square2 객체의 넓이는? {square2.height*square2.width}')
# square1 객체의 넓이는? 144
# square2 객체의 넓이는? 200

print('='*30)
#객체 생성
square3 = Square(12.4, 20.7, 'green')
print(square3.color) # green // 개별속성접근
# 메소드 호출
square3.print_info()
'''
 사각형의 색상 : green
 사각형의 가로 : 12.4
 사각형의 세로 : 20.7
'''
square3.print_area()
# 12.4X20.7 = 256.68

 

'''
Quiz

계산기 Calculator 클래스 만들기
2개의 숫자를 속성으로 가진 계산기
4개의 메소드 (더하기 / 빼기 / 곱하기 / 나누기)
인스턴스화 시킨 후 다음과 같이 출력한다

'''
class Calculator:
    def __init__(self, x, y):
        self.x = x
        self.y = y 
    
    # return 문이 있는 형태의 메소드 정의
    
    def plus(self):
        return self.x + self.y
    
    def minus(self):
        return self.x - self.y
    
    def multy(self):
        return self.x * self.y
    
    def divide(self):
        return round(self.x / self.y , 2)
    
    # return 문이 없는 형태의 메소드 정의
    
    def print_calculate(self) :
        print('     계산 결과     ')
        print(f' {self.x} + {self.y} = {self.plus()}')
        print(f' {self.x} - {self.y} = {self.minus()}')
        print(f' {self.x} X {self.y} = {self.multy()}')
        print(f' {self.x} / {self.y} = {self.divide()}')

# 객체화
calculator1 = Calculator(10, 3)
# 객체 속성으로 접근해서 출력
print(f'첫번째 숫자 : {calculator1.x}')
print(f'두번째 숫자 : {calculator1.y}')
# 객체 메소드로 접근해서 출력
print(f' 더하기 : {calculator1.plus()}')
print(f' 빼기 : {calculator1.minus()}')
print(f' 곱하기 : {calculator1.multy()}')
print(f' 나누기 : {calculator1.divide()}')
calculator1.print_calculate()

'''
결과)

첫번째 숫자 : 10
두번째 숫자 : 3
 더하기 : 13
 빼기 : 7
 곱하기 : 30
 나누기 : 3.33
     계산 결과
 10 + 3 = 13
 10 - 3 = 7
 10 X 3 = 30
 10 / 3 = 3.33

'''

# 메소드에 별도의 인자가 있는 경우의 클래스
# 속성 : kind, price, brand, source
# 메소드 : 정보 출력, 주문갯수에 따른 가격 출력 
class Bread:
    # 생성자 메소드
    def __init__(self, kind, price, source ):
        self.brand = '성심당' # 초기값이 있는 속성 정의\
        self.kind = kind
        self.price = price
        self.source = source
    # 빵 정보 출력 메소드
    
    def print_info(self):
        print(f' 브랜드 : {self.brand}')
        print(f' 빵 종류 : {self.kind}')
        print(f' 가격 : {self.price}')
        print(f' 재료 : {self.source}')
    
    # 가격 계산 출력 메소드
    def print_order(self, n):
        print(f' {self.kind}를(을) {n} 개 주문하셨습니다.')
        print(f' 주문 가격은? {self.price}X{n} = {self.price*n}')

# 객체화
bread1 = Bread('모카빵', 5500, ['밀가루', '설탕', '향신료', '버터'])
bread2 = Bread('팥빵', 2900, ['밀가루', '이스트', '팥'])
print('='*20)
bread1.print_info()
print()
bread2.print_info()
print()
bread1.print_order(10)
print()
bread2.print_order(5)

 

2. 클래스 변수

'''
# 클래스 변수 
: 인스턴스 공통 변수
: 클래스명.변수명, 인스턴스명.변수명
: 클래스 내부에서 생성자메소드(__init__()) 위에 선언
  변수명 = 데이터
'''
class Bread:
    # 클래스 변수 선언
    brand = '성심당'
    def __init__(self, kind, price, source ):
        self.kind = kind
        self.price = price
        self.source = source
    # 빵 정보 출력 메소드
    
    def print_info(self):
        print(f' 브랜드 : {self.brand}')
        print(f' 빵 종류 : {self.kind}')
        print(f' 가격 : {self.price}')
        print(f' 재료 : {self.source}')
    
# 클래스명.클래스변수명으로 호출 가능
print(Bread.brand)    
# 객체화 
bread1 = Bread('모카빵', 5500, ['밀가루', '설탕', '향신료', '버터'])
bread2 = Bread('팥빵', 2900, ['밀가루', '이스트', '팥'])
bread1.print_info()
'''
 브랜드 : 성심당
 빵 종류 : 모카빵
 가격 : 5500
 재료 : ['밀가루', '설탕', '향신료', '버터']
 '''
print()
bread2.print_info()
'''
 브랜드 : 성심당
 빵 종류 : 팥빵
 가격 : 2900
 재료 : ['밀가루', '이스트', '팥']
'''
print()
# id() : 저장되는 메모리 번지 반환
print(id(Bread.brand))
print(id(bread1.brand))
print(id(bread2.brand))


#결과
'''
1797124133296
1797124133296
1797124133296  즉, 다 같은 곳에서 메모리 저장
'''

 

3. 상속

'''
상속이란?
- OOP 프로그램의 대표적인 특징
- 부모클래스(슈퍼클래스, 조상클래스)에서 선언된 속성과 메소드를 사용할 수 있는 기능
- 다중 상속 가능
- 상속의 장점 : 코드의 재사용



class 클래스명(부모클래스명1, 부모클래스명2...):

    명령어

'''

# 부모 클래스 선언
class Papa:
    first_name = '김'
    def info1(self):
        print('아파트, 차')

class Mama:
    family_name = '박'
    def info2(self):
        print('엔비디아 주식 100주, 오피스텔')

# 자식 클래스 선언
class Child(Papa, Mama):
    #생성자 메소드 정의
    def __init__(self, lastname):
        # 부모 클래스 생성자 메소드 선언
        # super().__init__()
        Papa.__init__(self)
        Mama.__init__(self)
        self.lastname = lastname
        # 메소드 정의
    def info3(self, obj) :
        print(obj)
# 인스턴스화

child1 = Child('철수')
child2 = Child('영희')
print( 'child1의 이름은?' , child1.first_name,child1.family_name,child1.lastname)
print( 'child2의 이름은?' , child2.first_name,child2.family_name,child2.lastname)
child1.info1()
child1.info2()
child1.info3('오토바이')
'''
child1의 이름은? 김 박 철수
child2의 이름은? 김 박 영희
아파트, 차
엔비디아 주식 100주, 오피스텔
오토바이
'''

'''
메소드 오버라이딩?
    상속관계에서 부모 클래스에 동일하게 선언된 메소드를 재정의하는 기능
    자식클래스에서 선언된 메소드가 우선순위가 높다.

'''

class Tiger :
    kind = '호랑이'
    def jump(self):
        print(f'{Tiger.kind} 처럼 점프하기')
    def cry(self):
        print(f'{self.kind} : 어흥 ~')
        
class Lion:
    kind = '사자'
    def cry(self):
        print(f'{self.kind} : 으르렁 ~')
        
class Liger(Tiger, Lion):
    kind = '라이거'
    # 부모 클래스 Tiger의 jump() 메서드가 오버라이딩
    def jump(self):
        print(f'{self.kind} 처럼 돌면서 점프하기')
    # 부모 클래스 Tiger의 jump() 메소드를 다시 정의
    def jump_papa(self):
        super().jump()    
        
# 객체화
liger = Liger()
liger.cry() # 동시에 가지고 있을때 먼저 상속받은것 나옴. # Tiger의 cry()
liger.jump() # Lion 의 jump()
liger.jump_papa() # Tiger 의 jump

'''
결과)

라이거 : 어흥 ~
라이거 처럼 돌면서 점프하기
호랑이 처럼 점프하기

'''

 

'Python' 카테고리의 다른 글

16. CSV  (0) 2024.10.11
15. 파일 입출력  (0) 2024.10.11
14. 예외처리  (0) 2024.10.11
13. 모듈 사용하기(math 모듈, random 모듈)  (4) 2024.10.08
12. 함수( 반환값, 매개변수, 람다함수, filter(), map())  (3) 2024.10.08