본문 바로가기
Computer Science/[20-3,4] Python Basic

[Python] Operator Overloading (2) iterator 구현해보기

by gojw 2020. 4. 2.

 

Operator Overloading 1편:

https://jiwonkoh.tistory.com/48

 

[Python] Operator Overloading (1). == 연산자 재정의하기

<목차> ① Data Model (Object Model)이란? ② Dunder Method (Dunder Attributes)란? ▶ Dunder Method는 어디에 쓰이나? ③ Operator Overloading, 연산자 오버로딩이란? ▶ 비교연산자 ==를 재정의해보자 ① Da..

jiwonkoh.tistory.com

<목차>

▶ (문제) 두 개의 클래스 객체의 알파벳이 같으면 비교연산자 ==가 True다!

▶ (추가문제) 클래스 객체를 iterable하게 만드려면?

▶ iterator와 iterables의 차이

 

▶ (문제) 두 개의 클래스 객체의 알파벳이 같으면 비교연산자 ==가 True다!

이런 문제는 어떻게 풀 수 있을까?

클래스 객체 두 개를 만들고, 그 객체 안에 있는 알파벳 수가 같으면, ==가 True도록 하는 것이다.

이 문제도 Operator Overloading을 이용해서 풀 수 있다.

앞에서 보았듯이, 비교연산자의 Dunder method는 __eq__(self, other)이다.

이를 클래스 안에 넣어서 ==를 재정의해주면 되겠구나!.. 싶었지만..

class my_class:
    def __init__(self, letter):
        self.index = 0
        self.letter = letter

    def __eq__(self, other):
        num1 = sum(x.isalpha() for x in self)
        num2 = sum(y.isalpha() for y in other)

        return True if num1 == num2 else False

a = my_class('abc123')
b = my_class('def456')
print(a == b)
# False

그렇다면 이 코드만 클래스에 추가해주면 될까? 답은 No이다. 왜냐하면 본인이 만든 클래스 객체는 iterable하지 않기 때문이다.

파이썬의 내장 자료형으로는 쉽게 써온 for문을 돌릴 수 없다는 것이다.

 

 

▶ (추가문제) 클래스 객체를 iterable하게 만드려면?

클래스 객체를 iterable하게 하려면 다음과 같이 짜야한다.

class my_class:
    def __init__(self, letter):
        self.index = 0
        self.letter = letter

    def __iter__(self):
        return self

    def __next__(self):
        try:
            result = self.letter[self.index]
        except IndexError:
            raise StopIteration
        self.index += 1

        return result

    def __eq__(self, other):
        num1 = sum(x.isalpha() for x in self)
        num2 = sum(y.isalpha() for y in other)

        return True if num1 == num2 else False

a = my_class('abc123')
b = my_class('def456')
print(a == b)
# True

하나씩 살펴보자.

 

def __init__(self, letter):
    self.index = 0
    self.letter = letter

→ 클래스의 생성자이다. iterator을 만드는데 쓸 index 변수를 만들고, self.letter라는 인스턴스 변수를 만든다.

 

def __iter__(self):
    return self

def __next__(self):
    try:
        result = self.letter[self.index]
    except IndexError:
        raise StopIteration
    self.index += 1

    return result

 객체를 iterable하게 만들기 위해서는 두가지 메소드를 사용한다. __iter__()과 __next__()이다. 

이 두가지를 합친 것을 iterator protocol이라고 한다.

두 메소드의 역할을 알기 위해서는 iterator와 iterables의 차이를 알아야한다.

 

 

iterator와 iterables의 차이

(1) Iterables란?

반복할 수 있는 것을 뜻한다. 대부분 요소를 담고있는 컨테이너를 말하는데, 리스트, 튜플, 딕셔너리가 예시이다.

(2) Iterator란?

iterable을 반복하기 위해서는 iterator을 써야한다. iterator란 반복문을 작동할 수 있게 해주는 객체이다.

리스트를 반복하는 경우에, iterator는 현재 어디를 반복하고 있는지 추적해준다.

 

(1) __iter__()의 역할?

iterator 객체로 바꾸어 리턴하고, 반복문의 시작에 호출된다. = 반복할 객체를 부른다고 생각하면 쉽다.

(2) __next__()의 역할?

객체의 다음 값을 반환하고, 반복문이 시작된 다음에 호출된다. 더 이상 리턴할 값이 없는 경우에 StopIteration 예외가 발생한다. 이 에러는 반복문의 반복을 멈추는 데 사용한다.

댓글