IT world

[Python] 24.01.12 클래스 반복 본문

모두의 연구소(오름캠프)/AI 모델 활용 백엔드 개발 과정

[Python] 24.01.12 클래스 반복

엄킹 2024. 1. 12. 17:40

오늘은 오전에 개발자가 준비해야하는 포트폴리오라는 주제로 특강이 있었다. 

그렇게 강의를 듣고 오늘의 시작도 클래스!

 

너무 중요한 내용이고, 해당 지식을 정확하게 알고 있어야 하기 때문에 반복적으로 학습을 하고 있다.

1. 클래스

객체지향이란 것이 나타나기 전엔 프로그램이 어떤 일을 하고 나서 그 다음엔 어떤 일을 하고, 또 그 다음엔 어떤 작업을 할지에 대해서 우리는 작성하기 바빴다. 이 후 객체지향 프로그래밍이 나타나고 나서는 프로그램을 작성할 대상이 되는 실제 세계의 사물을 그대로 표현하고, 그것들이 어떻게 움직일지 정해주며 해당 객체가 어떻게 동작할지 만들었다. 

 

객체지향은 좋은 프로그램을 빨리 만들수도 있고, 유지보수에도 너무 좋고, 복잡한 프로그램을 작성하는데 많은 도움이 된다.

 

자..! 클래스는 하나의 큰 틀이자 설계도이다. 클래스가 정의되어있다면 쉽게 재사용할 수 있다는 장점이 있다.

예로 축수선수 박지성, 축구선수 안정환.. 두 사람 모두 실제로 존재하는 사람이다. 여기서 두 사람은 '축구선수'라는 공통점이 있다. 

 

이렇게 박지성과 안정환을 하나의 공통된 특징으로 표현할 수 있는 축구선수를 파이썬에선 클래스라 부르며 이런 축구선수의 개념으로 만들어진 선수들을 인스턴스라고 표현합니다. 

 

여기서 클래스(Class)에서 만들어지는 실체를 객체(Object) 라고 하며, 축구선수로부터 파생된 안정환, 박지성 같은 실존 인물이 객체에 해당한다. 보통 인스턴스(Instance)는 관계를 표현할 때 주로 사용된다. Class와 객체의 관계를 표현할 때 박지성은 축구선수의  인스턴스라고 표현한다.

 박지성, 안정환, 이영표는 모두 축구선수의 인스턴스야 (관계를 표현)
 박지성, 안정환, 이영표는 모두 객체야 (실체를 명명)

 

꼭 클래스를 사용해야하는 것은 아니다. 기본자료형, 클로저, 함수 등 클래스를 대신할 수 있는 방법은 다양하다.

하지만 그래도 클래스를 사용하는 이유는 클래스로 선언한 객체는 독립적이며 하나의 객체의 상태를 변경해도 다른 객체에 영향을 미치지 않기 때문에 관리에 용이하다. 추가로 데이터의 양부터 확장성, 재사용성, 가독성 등 다양한 이유가 있다. 

 

2. 상속

클래스의 상속은 하나의 클래스의 특성(속성 및 메서드)을 다른 클래스가 가져오는 것을 의미한다. 상속은 코드의 재사용성을 높일 수 있고 모듈성을 강화할 수 있다.

 

기존에 정의한 클래스의 속성 및 메서드를 그대로 사용할 수 있도록 클래스 간에 받는 것을 의미하며 중복된 메서드를 재정의할 필요가 없다는 장점이 있다.

기존 클래스에서 일부 기능을 추가하거나 변경함으로써 새로운 클래스를 정의할 수 있기 때문에 효율적인 코드 작성이 가능하다.

  • 상속해주는 기존 클래스는 부모클래스(Parent class), 상위클래스(Super class), 기초클래스(Base class)라 부른다.
  • 상속을 받는 클래스는 자식클래스(Child class), 하위클래스(Sub class), 파생클래스(Derived class)라고 부른다.
  # 상속 기본 구조
  class Car:
      speed = 100
      
      def __init__(self, name):
      	  self.name = name
      
      def move(self):
          pass


  class HybridCar(Car):
      def __init__(self, name):
          super().__init__(name)
      
      def move(self): # 메서드 오버라이딩
          print('움직입니다.')

 

위 코드를 보면 HybridCar 클래스는 Car 클래스를 상속했고, HybridCar Class 는 자식 클래스 Car Class는 부모 클래스가 된다. 자식 클래스는 부모 클래스의 속성과 메서드를 사용할 수 있으며 부모 클래스의 메서드를 오버라이딩(재정의)하여 기능을 수정할 수 있다.

 

* 메소드 오버라이딩

오버라이딩은 부모 클래스의 메소드를 자식 클래스에서 재정의 하여 사용하는 것을 의미한다. 

상속받은 메서드의 변수, 기능, 구조 등을 자식클래스에서 목적에 맞게 변형하여 사용할 수 있다.

 

위코드를 확인하면 자식클래스에서 move()함수를 재정의한 것을 확인할 수 있다.

 

아래코드는 부모의 메서드를 호출하는 예제이다.

  # 부모의 메서드를 재구현 ==> "메서드 오버라이딩"
  class A:
      def hello(self):
          print('hello world A')
    

  class B(A):
      def hello(self):
          print('hello world B')


  class C(A):
      pass


  a = A()
  b = B()
  c = C()

  a.hello()
  b.hello()
  c.hello()

 

또한, 매직메서드의 역할을 클래스 내에서 재정의하는 내용도 확인하였다.

리스트의 덧셈 연산은 리스트의 연결이 되지만, 클래스 내 __add__함수를 정의하여 리스트 내 원소의 합으로 수정했다.

# 원래 기능: [1,2,3] + [1,2,3] = [1,2,3,1,2,3]  
# 바꿀 기능: [1,2,3] + [1,2,3] = [2,4,6]  

# 행렬 class
class Matrix:
    def __init__(self, value):
        self.value = value 

    def __add__(self, next): 
        result = []
        for i, _ in enumerate(self.value): 
            result.append(self.value[i] + next.value[i])
        return result

    # 문자열 출력형태를 바꾼다
    def __str__(self):
        return str(self.value)
    
    # 문자열 출력형태를 바꾼다
    def __repr__(self):
        return str(self.value)

a = Matrix([1,2,3])
b = Matrix([1,2,3])

print(a) # 원래는 메모리 정보가 나오는데 __str__을 바꿈
a + b

 

3. 이터레이터(Iterator)

이터레이터란? 순서대로 다음 원소들에 차례대로 접근할 수 있는 객체이다. 

파이썬에서는 반복 가능한 객체(iterable)를 대상으로 이터레이터를 생성할 수 있다. 여기서 리스트, 튜플, 문자열 등이 대표적인 반복 가능한 객체이고, 이터레이터를 사용하면 대용량 데이터를 처리할 때 메모리를 효율적으로 관리하면서 데이터를 처리할 수 있다. 

 

그렇다면 클래스를 사용하여 이터레이터를 만들려면 어떻게 해야할까?

 

이터레이터를 만들기 위해서는 __iter__와 __next___ 메서드를 구현해야한다. 

    # 1. 이터레이터
    class MyIterator:
        def __init__(self, stop): 
            self.currentValue = 0
            self.stop = stop

        def __iter__(self): 
        	self.currentValue = 0
            return self

        def __next__(self): 
            if self.currentValue >= self.stop:
                raise StopIteration
            result = self.currentValue
            self.currentValue += 1
            return result

    my_iterator = MyIterator(5)

 

 

__iter__메서드는 이터레이터 객체를 반환하는 메서드로 MyIterator 클래스에 의해 생성되는 객체를 의미하는 self를 반환하도록 했다.

__next__메서드는 next() 함수 호출 시 수행되므로 MyIterator 객체 생성 시 전달한 데이터를 하나씩 반환하도록 했다.

 

즉 __iter__ 메서드를 통해 객체를 초기화하고 반환하며, __next__ 메서드를 통해 다음 원소를 반환하도록 했다.

 

Comments