데이터 엔지니어링 과정/python

[6일차] 객체와 클래스

오리는짹짹 2022. 12. 27. 22:05
목차
1. 클래스 선언과 객체 생성
2. 클래스를 구성하는 변수와 함수
3. 객체와 클래스를 사용하는 이유
4. 클래스 상속

1. 클래스 선언과 객체 생성

1. 객체란?

  • 속성과 행위로 구성된 대상을 의미
    속성 : 상태, 특징
    행위 : 행동, 동작, 기능
  • 변수와 함수의 묶음
    객체 : 사람
    변수 : 키, 몸무게, 이름
    함수: 걷기, 뛰기

2. 클래스 선언

3. 객체 생성 및 활용

class Bicycle():#클래스 선언
    pass
  • 클래스로부터 인스턴스 (instance)인 객체 선언
    객체명 = 클래스명()
my_bicycle = Bicycle()

my_bicycle
>>> <__main__.Bicycle at 0x1f27ad05eb0>
  • 객체에 속성 추가하기
    객체명.변수명 = 속성값
my_bicycle.wheel_size = 26
my_bicycle.color = 'black'
  • 속성 가져오기
    객체명.변수명
print("바퀴 크기:",my_bicycle.wheel_size) #객체의 속성 출력
print("색상:", my_bicycle.color)

>>> 바퀴 크기: 26
>>> 색상: black
  • 함수 추가
class Bicycle():
    def move(self, speed):
        print("자전거: 시속 {0}킬로미터로 전진".format(speed))
        
    def turn(self, direction):
        print("자전거: {0}회전".format(direction))
        
    def stop(self):
        print("자전거({0},{1}): 정지 ".format(self.wheel_size, self.color))
  • 객체의 메서드를 호출
    객체명.메서드명(인자1, 인자2)
my_bicycle = Bicycle() #Bicycle 클래스의 인스턴스인 my_bicycle 객체 생성

my_bicycle.wheel_size = 26 #객체의 속성 설정
my_bicycle.color = 'black'

my_bicycle.move(30) # 객체의 메소드 호출
my_bicycle.turn('좌')
my_bicycle.stop()

>>> 자전거: 시속 30킬로미터로 전진
>>> 자전거: 좌회전
>>> 자전거(26,black): 정지
bicycle_1 = Bicycle() #Bicycle 클래스의 인스턴스인 my_bicycle 객체 생성

bicycle_1.wheel_size = 27 #객체의 속성 설정
bicycle_1.color = 'red'

bicycle_1.move(20) # 객체의 메소드 호출
bicycle_1.turn('좌')
bicycle_1.stop()

>>> 자전거: 시속 20킬로미터로 전진
>>> 자전거: 좌회전
>>> 자전거(27,red): 정지
bicycle_2 = Bicycle() #Bicycle 클래스의 인스턴스인 my_bicycle 객체 생성

bicycle_2.wheel_size = 24 #객체의 속성 설정
bicycle_2.color = 'blue'

bicycle_2.move(24) # 객체의 메소드 호출
bicycle_2.turn('우')
bicycle_2.stop()

>>> 자전거: 시속 24킬로미터로 전진
>>> 자전거: 우회전
>>> 자전거(24,blue): 정지

4. 객체 초기화

  • init 함수
    - 객체를 생성하는 것과 동시에 속성값을 지정할 수 있다.
    - 생성될 때, 가장 먼저 자동으로 실행되기 때문에 속성을 초기화 할 수 있다.
class Bicycle():
    
    def __init__(self, wheel_size, color):
        self.wheel_size = wheel_size
        self.color = color
    
    def move(self, speed):
        print("자전거: 시속 {0}킬로미터로 전진".format(speed))
        
    def turn(self, direction):
        print("자전거: {0}회전".format(direction))
        
    def stop(self):
        print("자전거({0},{1}): 정지 ".format(self.wheel_size, self.color))
  • 더 편하게 만들 수 있게 된  객체
my_bicycle=Bicycle(26,'black') #객체 생성과 동시에 속성값을 지정

my_bicycle.move(30) # 객체의 메소드 호출
my_bicycle.turn('좌')
my_bicycle.stop()

>>> 자전거: 시속 30킬로미터로 전진
>>> 자전거: 좌회전
>>> 자전거(26,black): 정지

 

2. 클래스를 구성하는 변수와 함수

1. 클래스에서 사용하는 변수

  • 클래스 변수
    - 클래스 내에 있지만, 함수 밖에서 '변수명 = 데이터' 형식으로 정의
    - 모든 객체가 공통 사용 '클래스명.변수명'으로 사용
  • 인스턴스 변수
    - 함수 내에서 사용된 변수
    - 'self.변수명 = 데이터' 형식으로 정의한 변수
    - 'self.변수명'으로 접근 가능
class Car():
    instance_count = 0 # 클래스 변수 생성 및 초기화
    
    def __init__(self, size, color):
        self.size = size #인스턴스 변수 생성 및 초기화
        self.color = color # 인스턴스 변수 생성 및 초기화
        Car.instance_count = Car.instance_count + 1 # 클래스 변수 이용
        print(f"자동차 객체의 수 : {Car.instance_count}")
        
    def move(self):
        print("자동차{0} & {1}가 움직입니다.".format(self.size, self.color))
car1 = Car('small', 'white')
car2 = Car('big', 'black')

>>> 자동차 객체의 수 : 1
>>> 자동차 객체의 수 : 2
  • 클래스명.변수명으로 언제든 호출
print("Car 클래스의 총 인스턴스 개수 : {}".format(Car.instance_count))

>>> Car 클래스의 총 인스턴스 개수 ; 2
  • 모든 객체에서 공통으로 사용
print("Car 클래스의 총 인스턴스 개수:{}".format(car1.instance_count))
print("Car 클래스의 총 인스턴스 개수:{}".format(car2.instance_count))

>>> Car 클래스의 총 인스턴스 개수:2
>>> Car 클래스의 총 인스턴스 개수:2
  • 인스턴스 변수는 각 객체에서 별도로 관리
car1.move()
car2.move()

>>> 자동차small & white가 움직입니다.
>>> 자동차big & black가 움직입니다.
  • 이름이 같은 클래스 변수와 인스턴스 변수의 경우
class Car2():
    count = 0 #클래스 변수 생성 및 초기화
    
    def __init__(self, size, num):
        self.size = size #인스턴스 변수 생성 및 초기화
        self.count = num # 인스턴스 변수 생성 및 초기화
        Car2.count = Car2.count + 1 # 클래스 변수 이용
        print(f"자동차 객체의 수 : {Car2.count}")
        print("인스턴스 변수 초기화: self.count = {0}".format(self.count))
        
    def move(self):
        print("자동차{0} & {1}가 움직입니다.".format(self.size, self.color))
  • 변수 이름은 같지만 별개로 동작
car1 = Car2("big",20)
>>> 자동차 객체의 수 : 1
>>> 인스턴스 변수 초기화: self.count = 20

car2 = Car2("small",30)
>>> 자동차 객체의 수 : 2
인스턴스 변수 초기화: self.count = 30

2. 클래스에서 사용하는 함수 (인스턴스 메서드, 정적 메서드, 클래스 메서드)

  • 인스턴스 메서드
    : 각 객체에서 개별적으로 동작하는 함수를 만들고자 할 때 사용하는 함수

# Car 클래스 선언
class Car():
    instance_count = 0 # 클래스 변수 생성 및 초기화
    
    #초기화 함수(인스턴스 메서드)
    def __init__(self, size, color):
        self.size = size #인스턴스 변수 생성 및 초기화
        self.color = color # 인스턴스 변수 생성 및 초기화
        Car.instance_count = Car.instance_count + 1 # 클래스 변수 이용
        print(f"자동차 객체의 수 : {Car.instance_count}")
    
    #인스턴스 메서드
    def move(self,speed):
        self.speed=speed # 인스턴스 변수 생성
        print("자동차{0} & {1}가 ".format(self.size, self.color),end="")
        print("시속 {0}킬로미터로 전진".format(self.speed))
        
    #인스턴스 메서드
    def auto_cruise(self):
        print("자율 주행 모드")
        self.move(self.speed) #move()함수의 인자로 인스턴스 변수를 입력
car1 = Car("small", "red") # 객체 생성 (car1)
car2 = Car("big", "green") # 객체 생성 (car2)
>>> 자동차 객체의 수 : 1
>>> 자동차 객체의 수 : 2

car1.move(80) #객체 (car1)의 move() 메서드 호출
car2.move(100) #객체 (car2)의 move() 메서드 호출
>>> 자동차small & red가 시속 80킬로미터로 전진
>>> 자동차big & green가 시속 100킬로미터로 전진

car1.auto_cruise() #객체(car1)의 auto_cruise 메서드 호출
car2.auto_cruise() #객체(car2)의 auto_cruise 메서드 호출
>>> 자율 주행 모드
>>> 자동차small & red가 시속 80킬로미터로 전진
>>> 자율 주행 모드
>>> 자동차big & green가 시속 100킬로미터로 전진
  • 정적메서드
    - 클래스나 클래스의 인스턴스(객체)와는 무관하게 독립적으로 만들고 싶은 함수를 만들고 싶을 때 사용
    - 함수를 정의할 때 self 사용하지 않는다.
    - 함수 앞에 @staticmethod를 선언해서 정적 메서드 임을 표시
    - 구조

        - 날짜 및 시간 정보 제공, 환율 정보 제공, 단위 변환과 같이 객체와 관계없이 독립적으로 동작하는 함수를 만들 떄 사용 

# Car 클래스 선언
class Car():
    instance_count = 0 # 클래스 변수 생성 및 초기화
    
    # def __init__(self, size, color): => 앞의 코드 활용    
    # def move(self,speed): =>앞의 코드 활용       
    # def auto_cruise(self): =>앞의 코드 활용
        
    #정적 메서드
    @staticmethod
    def check_type(model_code):
        if (model_code >=20):
            print("이 자동차는 전기차입니다.")
        elif(10 <= model_code < 20):
            print("이 자동차는 가솔린차입니다.")
        else:
            print("이 자동차는 디젤차입니다.")
  • 클래스 메서드
    - 클래스 변수를 사용하기 위한 함수 
    - 함수를 정의할 때 첫 번째 인자로 클래스를 넘겨받는 cls가 필요하며, 이를 이용해 클래스 변수에 접근
    - 함수 앞에 @classmethod 지정해야 함
    - 구조

        - 생성된 객체의 개수를 반환하는 등 클래스 전체에서 관리해야 할 기능이 있을 때 주로 이용

 

# Car 클래스 선언
class Car():
    instance_count = 0 # 클래스 변수 
    
    # def __init__(self, size, color): => 앞의 코드 활용    
    # def move(self,speed): =>앞의 코드 활용       
    # def auto_cruise(self): =>앞의 코드 활용    
    #@staticmethod
    #def check_type(model_code):  =>앞의 코드 활용
     
    #클래스 메서드
    @classmethod
    def count_instance(cls):
        print("자동차 객체의 개수: {0}".format(cls.instance_count))

 

Car.count_instance() # 객체 생성 전에 클래스 메서드 호출

car1 = Car("small", "red") # 첫 번째 객체 생성
Car.count_instance() # 클래스 메서드 호출

car2 = Car("big", "green") # 두 번쨰 객체 생성
Car.count_instance() # 클래스 메서드 호출

>>> 자동차 객체의 개수 : 0
>>> 자동차 객체의 개수 : 1
>>> 자동차 객체의 개수 : 2

👀결과를 보면 객체를 생성할 때마다 클래스 변수 instance_count의 값이 1씩 증가한다.

 

3. 객체와 클래스를 사용하는 이유

1. 객체와 클래스를 사용하는 이유

  • 코드 관리가 편하다.
  • 큰 프로그램을 만들 때는 클래스와 객체를 많이 이용한다.
  • 유사한 객체가 많은 프로그램을 만들 때도 주로 클래스와 객체를 이용해 코드를 작성한다.

ex)위로만 이동할 수 있는 컴퓨터 게임의 로봇

  • 로봇의 속성과 동작
    - 속성: 이름, 위치
    - 동작; 한 칸 이동
  • 클래스와 객체를 사용하지 않을 시
    -한 대의 로봇 구현
robot_name = 'R1' #로봇 이름
robot_pos = 0 #로봇의 초기 위치

def robot_move():
    global robot_pos
    robot_pos = robot_pos + 1
    print("{0} position: {1}".format(robot_name, robot_pos))
robot_move()

>>> R1 position: 1

        -  두 대의 로봇 구현

robot1_name = 'R1' #로봇 이름
robot1_pos = 0 #로봇의 초기 위치

def robot1_move():
    global robot1_pos
    robot1_pos = robot1_pos + 1
    print("{0} position: {1}".format(robot1_name, robot1_pos))
    
    
robot2_name = 'R2' #로봇 이름
robot2_pos = 10 #로봇의 초기 위치

def robot2_move():
    global robot2_pos
    robot2_pos = robot2_pos + 1
    print("{0} position: {1}".format(robot2_name, robot2_pos))
robot1_move()
robot2_move()

>>> R1 position: 1
>>> R2 position: 11

👀로봇이 늘어날수록, 더 많은 변수와 함수가 필요해지면서 코드가 길어진다!

로봇 별로 변수와 함수의 역할이 같으므로, 클래스와 객체를 이용하면 편리함을 경험할 수 있다.

  • 클래스와 객체 사용
class Robot():
    def __init__(self,name,pos):
        self.name = name #로봇 객체의 이름
        self.pos = pos #로봇 객체의 위치
        
    def move(self):
        self.pos=self.pos+1
        print("{0} position: {1}".format(self.name, self.pos))

        -  객체 생성

robot1 = Robot('R1', 0)
robot2 = Robot('R2', 10)

        -  메서드 실행

robot1.move()
robot2.move()

>>> R1 position: 2
>>> R2 position: 12

        -  더 많은 객체 생성 및 메서드 실행

myRobot3 = Robot('R3', 30)
myRobot4 = Robot('R4', 40)

myRobot3.move()
myRobot4.move()

>>> R3 position: 31
>>> R4 position: 41

 

4. 클래스 상속

1. 클래스 상속

  • 상속 : 만들어진 클래스 변수와 함수를 이어받고 새로운 내용을 추가해 클래스를 선언하는 것
  • 부모 클래스(=슈퍼 클래스, 상위 클래스)와 자식 클래스(서브 클래스, 하위클래스)
  • 형식

ex)  부모 클래스인 자전거 클래스를 상속받아 자식 클래스인 접는 자전거 클래스 만들기

  • 부모 클래스
class Bicycle():
    
    def __init__(self, wheel_size, color):
        self.wheel_size = wheel_size
        self.color = color
    
    def move(self, speed):
        print("자전거: 시속 {0}킬로미터로 전진".format(speed))
        
    def turn(self, direction):
        print("자전거: {0}회전".format(direction))
        
    def stop(self):
        print("자전거({0},{1}): 정지 ".format(self.wheel_size, self.color))
  • 자식 클래스 FoldingBicycle()

class FoldingBicycle(Bicycle):
    
    def __init__(self, wheel_size, color, state): #FoldingBicycle 초기화
        Bicycle.__init__(self, wheel_size, color) #Bicycle의 초기화 재사용
        #super().__init__(wheel_size,color) #super()도 사용 가능
        self.state=state # 자식 클래스에서 새로 추가된 변수
        
    def fold(self):
        self.state = 'folding'
        print("자전거: 접기, state = {0}".format(self.state))
        
    def unfold(self):
        self.state = 'unfolding'
        print("자전거: 펴기, state = {0}".format(self.state))
folding_bicycle = FoldingBicycle(27, 'white', 'unfolding') #객체 생성

folding_bicycle.move(20) #부모 클래스의 함수(메서드) 호출
folding_bicycle.fold() #자식 클래스에서 정의한 함수 호출
folding_bicycle.unfold()

>>> 자전거: 시속 20킬로미터로 전진
>>> 자전거: 접기, state = folding
>>> 자전거: 펴기, state = unfolding