[플레이데이터]

[PlayData - Day 6] 객체와 클래스

EYZ27 2022. 12. 27. 17:53

1. K-Digital Training 과정

  • 빅데이터 기반 지능형SW 및 MLOps 개발자 양성과정 19기 (Day 6)

 

2. 목차

  1. 클래스 선언과 객체 생성
  2. 클래스를 구성하는 변수와 함수
  3. 객체와 클래스를 사용하는 이유
  4. 클래스 상속

 

3. 수업 내용

 

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

  • 클래스 선언
    class 클래스명():

    [변수1] # 클래스 변수   
    [변수2]    
    ...   

    def 함수1(self[, 인자1, 인자2, ..., 인자n]): 클래스 함수   
        <코드 블록>   
        ...   

    def 함수2(self[, 인자1, 인자2, ..., 인자n]): 클래스 함수   
        <코드 블록>   
        ...   
  • 객체 생성 및 활용
class Bicycle(): # 클래스 선언
    pass
  • 클래스로부터 인스턴스(instance)인 객체를 선언: 객체명 = 클래스명()
my_bicycle = Bicycle()
my_bicycle

>>> <__main__.Bicycle at 0x22e94e7dee0>
# 객체에 속성을 추가하기
# 객체명.변수명 = 속성값

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): 정지
bicycle1 = Bicycle() # Bicycle 클래스의 인스턴스인 bicycle1 객체 생성

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

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

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

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

bicycle2.move(15) # 객체의 메서드 호출
bicycle2.turn('우')
bicycle2.stop()

>>> 자전거: 시속 15킬로미터로 전진
>>> 자전거: 우회전
>>> 자전거(24, blue): 정지
  • 객체 초기화
    • 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. 클래스를 구성하는 변수와 함수

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

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

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

>>> Car 클래스의 총 인스턴스 개수: 2
>>> Car 클래스의 총 인스턴스 개수: 2
  • 클래스 변수 count와 인스턴스 변수 count가 별개로 동작할 수 있다.
class Car2():
    count = 0 # 클래스 변수 생성 및 초기화
    
    def __init__(self, size, num):
        self.size = size      # 인스턴스 변수 생성 및 초기화
        self.count = num    # 인스턴스 변수 생성 및 초기화
        Car2.count = Car2.count + 1 # 클래스 변수 이용
        print("자동차 객체의 수: Car2.count = {0}".format(Car2.count))
        print("인스턴스 변수 초기화: self.count = {0}".format(self.count))
        
    def move(self):
        print("자동차({0} & {1})가 움직입니다.".format(self.size, self.color))
        
        
car1 = Car2("big", 20)
car2 = Car2('small', 30)

>>> 자동차 객체의 수: Car2.count = 1
>>> 인스턴스 변수 초기화: self.count = 20
>>> 자동차 객체의 수: Car2.count = 2
>>> 인스턴스 변수 초기화: self.count = 30

print("Car2.count", Car2.count, "car1.count", car1.count)

>>> Car2.count 2 car1.count 20

 

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

      class 클래스명():

      def 함수명(self, 인자1, 인자2, ..., 인자n):   
          self.변수명1 = 인자1   
          self.변수명2 = 인자2   
          self.변수명3 = 데이터   
          ...   
          <코드 블록>   
    • 다음과 같이 객체를 생성한 후에 호출할 수 있다.
      객체명 = 클래스명() 객체명.메서드명(인자1, 인자2, 인자3, ..., 인자n)
# 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("자동차 객체의 수: {0}".format(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")
car2 = Car("big", "green")

car1.move(80)
car2.move(100)

car1.auto_cruise()
car2.auto_cruise()

>>> out >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
자동차 객체의 수: 1
자동차 객체의 수: 2
자동차(small & red)가 시속 80킬로미터로 전진
자동차(big & green)가 시속 100킬로미터로 전진
자율 주행 모드
자동차(small & red)가 시속 80킬로미터로 전진
자율 주행 모드
자동차(big & green)가 시속 100킬로미터로 전진
>>> out >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
  • 2) 정적 메서드
    • 정적 메서드는 클래스와 관련이 있어서 클래스 안에 두기는 하지만, 클래스나 클래스의 인스턴스와는 무관하게 독립적으로 동작하는 함수를 만들고 싶을 때 이용하는 함수.
      함수를 정의할 때 인자로 self를 이용하지 않으며, 정적 메서드 안에서는 인스턴스 메서드나 인스턴스 변수에 접근할 수 없다. 함수 앞에 데코레이터(Decorator) @staticmethod를 선언해 정적 메서드임을 표시한다.

      class 클래스명():

      @staticmethod   

      def 함수명([인자1, 인자2, ..., 인자n]):   

          <코드 블록>   
      클래스명.메서드명([인자1, 인자2, ..., 인자n]) 으로 사용한다.
# Car 클래스 선언
class Car():
    
    # 정적 매서드
    @staticmethod
    def check_type(model_code):
        if model_code >= 20:
            print("이 자동차는 전기차입니다.")
        elif 10 <= model_code < 20:
            print("이 자동차는 가솔린차입니다.")
        else:
            print("이 자동차는 디젤차입니다.")
            
            
Car.check_type(25)
Car.check_type(2)

>>> 이 자동차는 전기차입니다.
>>> 이 자동차는 디젤차입니다.
  • 3) 클래스 메서드
    • 클래스 변수를 사용하기 위한 함수.
      함수를 정의할 때 첫번째 인자로 클래스를 넘겨받는 cls가 필요
      데코레이터로 @classmethod를 지정

      class 클래스명():

      @classmethod   

      def 함수명(cls[, 인자1, 인자2, ..., 인자n]):   

          <코드 블록>   
# 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("자동차 객체의 수: {0}".format(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() 함수의 인자로 인스턴스 변수를 입력 (속도 유지)
        
#     # 정적 매서드
#     @staticmethod
#     def check_type(model_code):
#         if model_code >= 20:
#             print("이 자동차는 전기차입니다.")
#         elif 10 <= model_code < 20:
#             print("이 자동차는 가솔린차입니다.")
#         else:
#             print("이 자동차는 디젤차입니다.")
        
    @classmethod
    def count_instance(cls):
        print("자동차 객체의 개수: {0}".format(cls.instance_count))
        
        
Car.count_instance()

car1 = Car("small", "red")
car1.count_instance()

car2 = Car("big", "green")
car2.count_instance()

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

 

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

  • 코드 작성과 관리가 편하다.
  • 유사한 객체가 많은 프로그램을 만들 때도 클래스와 객체를 이용한다.
  • 예: 로봇이 여러대 나오는 컴퓨터 게임
    로봇의 속성: 이름, 위치
    로봇의 동작: 한 칸 이동
# 클래스와 객체를 사용하지 않을 시
robot_name = 'R1' # 로봇의 이름
robot_pos = 0     # 로봇의 초기 위치

def robot_move():
    global robot_pos
    robot_pos += 1
    print(f"{robot_name} position: {robot_pos}")
    
    
robot_move()

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

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

def robot2_move():
    global robot2_pos
    robot2_pos += 1
    print(f"{robot2_name} position: {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 += 1
        print(f"{self.name} position: {self.pos}")
        
robot1 = Robot('R1', 0)
robot2 = Robot('R2', 10)

robot1.move()
robot2.move()

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

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

>>> myRobot3.move()
>>> myRobot4.move()

 

4. 클래스 상속

  • 만들어진 클래스 변수와 함수를 이어받고 새로운 내용을 추가해 클래스를 선언할 수 있다.

    class 자식 클래스 이름(부모 클래스 이름):

    < 코드 블록 > 
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))
  • 자식 클래스 생성 방법
    부모 클래스 이름.함수명() 또는 super().함수명()을 사용한다.
class FoldingBicycle(Bicycle):
    
    def __init__(self, wheel_size, color, state): # FoldingBicycle 초기화
        Bicycle.__init__(self, wheel_size, color) # Bicycle의 초기화 재사용
        #super().__init__(wheel_size, color)      # super()도 Bicycle대신 사용 가능
        self.state = state                        # 자식 클래스에서 새로 추가한 변수
        
    def fold(self):
        self.state = 'folding'
        print(f'자전거: 접기, state = {self.state}')
        
    def unfold(self):
        self.state = 'unfolding'
        print(f'자전거: 펴기, state = {self.state}')
        
        
folding_bicycle = FoldingBicycle(27, 'white', 'unfolding') # 객체 생성

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


>>> 자전거: 시속 20킬로미터로 전진
>>> 자전거: 접기, state = folding
>>> 자전거: 펴기, state = unfolding
  • 클래스 상속과 오버라이딩
class SportsTeam:
    def __init__(self, team_name):
        self.team_name = team_name
        print(f'{self.team_name} 팀에 대한 정보입니다.')
        
    def won(self, won):
        print(f'{self.team_name} 팀은 {won}회 승리하였습니다.')
    
    def loss(self, loss):
        print(f'{self.team_name} 팀은 {loss}회 패배하였습니다.')
    
    def draw(self, draw):
        print(f'{self.team_name} 팀은 {draw}회 비겼습니다.')
# 상속

class SoccerTeam(SportsTeam):
    def __init__(self, team_name):
        self.team_name = team_name
        
class BasketballTeam(SportsTeam):
    def __init__(self, team_name):
        self.team_name = team_name
mcfc = SoccerTeam('Manchester City FC')
mcfc.won(1)
mcfc.loss(2)
mcfc.draw(3)

lal = BasketballTeam('LA Lakers')
lal.won(4)
lal.loss(5)
lal.draw(6)


>>> out >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Manchester City FC 팀은 1회 승리하였습니다.
Manchester City FC 팀은 2회 패배하였습니다.
Manchester City FC 팀은 3회 비겼습니다.
LA Lakers 팀은 4회 승리하였습니다.
LA Lakers 팀은 5회 패배하였습니다.
LA Lakers 팀은 6회 비겼습니다.
>>> out >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
# 오버라이딩

class BasketballTeam(SportsTeam):
    def __init__(self, team_name):
        self.team_name = team_name  
    def draw(self, draw):
        print(f'{self.team_name} 팀은 {draw}회 연장전에 돌입했습니다')
        
        
lal = BasketballTeam('LA Lakers')
lal.draw(6)

>>> LA Lakers 팀은 6회 연장전에 돌입했습니다
  • 슈퍼(super) 함수는 부모 클래스 내 메서드를 자식 클래스에서 이용하면서 동시에 필요한 부분만 재정의하여 사용
class BasketballTeam(SportsTeam):
    def __init__(self, team_name):
        self.team_name = team_name  
    def draw(self, draw):
        super().draw(draw)
        print(f'{self.team_name} 팀은 {draw}회 연장전에 돌입했습니다')
        
        
lal = BasketballTeam('LA Lakers')
lal.draw(6)

>>> out >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
LA Lakers 팀은 6회 비겼습니다.
LA Lakers 팀은 6회 연장전에 돌입했습니다
>>> out >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>