티스토리 뷰

8.5 연산자 오버로딩과 특수 메소드(Operator Overloading and Special Methods)

* 오버로딩(overloading)오버라이딩(overriding) 개념을 간단하게나마 숙지하고 게시물을 봐주세요.

오버로딩(overloading) : 메소드의 '중복 정의'

오버라이딩(overriding) : 메소드의 '재정의'

이번 섹션의 주제는 '연산자' 오버로딩이기 때문에, '연산자'를 이용해서 메소드를 정의하고, 이렇게 중복 정의한 '메소드'를 사용하는 방법을 다룹니다.

메소드 오버로딩, 오버라이딩과 헷갈리는 경우가 없으시길 바랍니다.

 

- 파이썬에서 당신은 어떤 연산자함수의 동작을 똑같이 수행하는 메소드를 정의 할 수 있다.

- 이러한 연산자를 메소드로 정의하는 것을 우리는 연산자 오버로딩(operator overloading)이라 부른다.

- 연산자 오버로딩(operator overloading)은 프로그래머가 정의내린 메소드에 내장 연산자(built-in operator)를 사용하여 정의한다.

- 메소드 앞 뒤에 밑줄 두개(__)를 이용하여 정의한다. 예를 들어 + 연산자를 메소드로 이용하기 위해서 메소드 이름을 __add__라고 정의 할 수 있다.

- 밑줄(__)이 있다고 해서 이 메소드가 private를 의미하는 것은 아니다.

 

*연산자 오버로딩 : 연산자와 특수 메소드(이미 파이썬에서 정의해놓은 메소드)

연산자/함수(Operator/Function) 

 메소드(Method)

 설명(Description)

 +

 __add__(self, other) 

 덧셈 

 *

 __mul__(self, other)

 곱셈

 -

 __sub__(self, other) 

 뺄셈 

 /

 __truediv__(self, other)

 나눗셈 

 %

 __mod__(self, other) 

 나머지

 <

 __lt__(self, other) 

 작다(미만) 

 <=

 __le__(self, other) 

 작거나 같다(이하) 

 ==

 __eq__(self, other) 

 같다 

 !=

 __ne__(self, other) 

 같지 않다 

 >

 __gt__(self, other) 

 크다(초과)

 >=

 __ge__(self, other) 

 크거나 같다(이상) 

 [index]

 __getitem__(self, index) 

 인덱스 연산자 

 in

 __contains__(self, value)

 멤버 확인  

 len

 __len__(self)

 요소 길이 

 str

 __str__(self)

 문자열 표현 

 

* 특수 메소드를 이용한 예제

1
2
3
4
5
s1 = "Washington"
s2 = "California"
print("the first character in s1 is", s1.__getitem__(0))
print("s1 + s2 is", s1.__add__(s2))
print("s1 < s2?", s1.__lt__(s2))
cs

* 그외 예제 코드들

ex1)

1
2
3
s1 = "Washington"
print("Is W in s1?"'W' in s1)
print("Is W in s1?", s1.__contains__('W'))
cs

ex2)

1
2
3
s1 = "Washington"
print("The length of s1 is"len(s1) )
print("The length of s1 is", s1.__len__())
cs

 

- 연산자 오버로딩(operator overloading)을 이용했을 때 장점은 코드를 읽기 쉬워지고 유지하는데도 도움이 된다.

 

8.6 사례 연구: Rational 클래스(Case Study: The Rational Class)

- 이번 섹션에서는 유리수(rational number)를 표현하고 사용하는 Rational 클래스 디자인에 대해 다룬다.

- 유리수는 a/b와 같은 형식의 분모(denominator)와 분자(numerator)로 이루어져 있다. 예를 들어, 1/3, 3/4, 10/4는 유리수(rational numbers)이다.

- 유리수의 분모는 0이 될 수 없다는 걸 기억하자.

- 모든 정수 i는 유리수 i/1와 대등하다.

- 유리수(rational number)는 정확한 계산을 이용해 표현된다. 예를 들어, 1/3 = 0.3333....

- 위의 숫자는 float 데이터 타입으로 정확하게 표현되지 않는다. 정확한 결과를 얻기 위해서 우리는 유리수를 사용하여야만 한다.

- 파이썬정수(integers)와 소수점 숫자(floating-point numbers) 데이터 타입은 제공하지만, 유리수를 위한 데이터 타입은 제공되지 않는다.

- 이번 섹션에서는 유리수를 위한 클래스를 디자인 하는 방법을 배워볼 예정이다.

 

* Rational 클래스의 UML 클래스 다이어그램

- 예를 들어, 1/3 = 2/6 = 3/9 = 4/12와 같은 수가 똑같은 유리수들은 1/3과 같은 최소 단위로 출력되어야 한다.

- 최소단위로 만드는 횟수를 줄이기 위해, 분자와 분모의 최대 공약수를 찾아 약분하도록 만든다.

 

* 본 프로그램(TestRationalClass.py)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import Rational
 
#유리수 r1과 r2 초기화
r1 = Rational.Rational(42)
r2 = Rational.Rational(23)
 
#Display results
print(r1, "+", r2, "=", r1+r2)
print(r1, "-", r2, "=", r1-r2)
print(r1, "*", r2, "=", r1*r2)
print(r1, "/", r2, "=", r1/r2)
 
print(r1, ">", r2, "is", r1 > r2)
print(r1, ">=", r2, "is", r1 >= r2)
print(r1, "<", r2, "is", r1 < r2)
print(r1, "<=", r2, "is", r1 <= r2)
print(r1, "==", r2, "is", r1 == r2)
print(r1, "!=", r2, "is", r1 != r2)
 
print("int(r2) is"int(r2))
print("float(r2) is", float(r2))
 
print("r2[0] is", r2[0])
print("r2[1] is", r2[1])
cs

 

* Rational 클래스(Rational.py)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
class Rational:
    def __init__(self, numerator = 0, denominator = 1):
        divisor = gcd(numerator, denominator)
        self.__numerator = (1 if denominator > 0 else -1) \
            * int(numerator / divisor)
        self.__denominator = int(abs(denominator) / divisor)
 
    # 자신의 유리수에 지정된 유리수를 더한다.
    def __add__(self, secondRational):
        n = self.__numerator * secondRational[1+ \
            self.__denominator * secondRational[0]
        d = self.__denominator * secondRational[1]
        return Rational(n, d)
 
    # 자신의 유리수에서 지정된 유리수를 뺀다.
    def __sub__(self, secondRational):
        n = self.__numerator * secondRational[1- \
            self.__denominator * secondRational[0]
        d = self.__denominator * secondRational[1]
        return Rational(n, d)
 
    # 자신의 유리수와 지정된 유리수를 곱한다.
    def __mul__(self, secondRational):
        n = self.__numerator * secondRational[0]
        d = self.__denominator * secondRational[1]
        return Rational(n, d)
 
    # 자신의 유리수를 지정된 유리수로 나눈다.
    def __truediv__(self, secondRational):
        n = self.__numerator * secondRational[1]
        d = self.__denominator * secondRational[0]
        return Rational(n, d)
 
    # 자신의 유리수를 실수 값으로 반환한다.
    def __float__(self):
        return self.__numerator / self.__denominator
 
    # 자신의 유리수를 정수 값으로 반환한다.
    def __int__(self):
        return int(self.__float__())
 
    # 문자열 표현을 반환한다.
    def __str__(self):
        if self.__denominator == 1:
            return str(self.__numerator)
        else:
            return str(self.__numerator) + "/" + str(self.__denominator)
 
    def __lt__(self, secondRational):
        return self.__cmp__(secondRational) < 0
 
    def __le__(self, secondRational):
        return self.__cmp__(secondRational) <= 0
 
    def __gt__(self, secondRational):
        return self.__cmp__(secondRational) > 0
 
    def __ge__(self, secondRational):
        return self.__cmp__(secondRational) >= 0
 
    # 두 숫자를 비교한다.
    def __cmp__(self, secondRational):
        temp = self.__sub__(secondRational)
        if temp[0> 0:
            return 1
        elif temp[0< 0:
            return -1
        else:
            return 0
 
    # 인덱스 연산자를 사용하여 분자와 분모를 반환한다.
    def __getitem__(self, index):
        if index == 0:
            return self.__numerator
        else:
            return self.__denominator
 
def gcd(n, d):
    n1 = abs(n);
    n2 = abs(d)
    gcd = 1
 
    k = 1
    while k <= n1 and k <= n2:
        if n1 % k == 0 and n2 % k == 0:
            gcd = k
        k += 1
 
    return gcd
 
cs

 

 

참고 문헌 : Introduction to Programming Using Python / Y.DANIEL LIANG



본 게시물은 개인적인 용도로 작성된 게시물입니다. 이후 포트폴리오로 사용될 정리 자료이니 불펌과 무단도용은 하지 말아주시고 개인 공부 목적으로만 이용해주시기 바랍니다.


교재 영어 원서를 직접 번역하여 정리한 게시물이므로 일부 오타, 의역이 존재할 수 있습니다. 틀린 부분이 있다면 댓글로 알려주시면 감사하겠습니다. 

 

 

댓글