Do it! 점프 투 파이썬

Chapter 05-1 클래스_2

판다조아 2022. 6. 7. 00:32

사칙연산 클래스 만들기

'백견이 불여 일타'라고 했다. 클래스를 직접 만들며 배워 보자.

여기에서는 사칙연산을 쉽게 해주는 클래스를 만들어 볼 것이다. 사칙연산은 더하기.빼기.나누기.곱하기를 말한다.

 

 

클래스를 어떻게 만들지 먼저 구상하기

클래스는 무작정 만드는 것보다 클래스로 만든 객체를 중심으로 어떤 식으로 동작하게 할 것인지 미리 구상을 한 후에 생각한 것들을 하나씩 해결하면서 완성해 나가는 것이 좋다.

사칙연산을 가능하게 하는 FourCal 클래스가 다음처럼 동작한다고 가정해 보자.

 

먼저 a = FourCal( )를 입력해서 a라는 객체를 만든다.

>>> a = FourCal( )

 

그런 다음 a.setdata(4, 2)처럼 입력해서 숫자 4와 2를 a에 지정해 주고

>>> a.setdata(4, 2)

 

a.add( )를 수행하면 두 수를 합한 결과(4 + 2)를 돌려주고

>>> print(a.add( ))
6

 

a.mul( )을 수행하면 두 수를 곱한 결과(4 * 2)를 돌려주고

>>> print(a.mul( ))
8

 

a.sub( )를 수행하면 두 수를 뺀 결과(4 - 2)를 돌려주고

>>> print(a.sub( ))
2

 

a.div( )를 수행하면 두 수를 나눈 결과(4 / 2)를 돌려준다.

>>> print(a.div( ))
2

 

이렇게 동작하는 FourCal 클래스를 만드는 것이 바로 우리의 목표이다.

 

 

 

클래스 구조 만들기

자, 그러면 지금부터 앞에서 구상한 것처럼 동작하는 클래스를 만들어 보자. 제일 먼저 할 일은 a = FourCal( )처럼 객체를 만들 수 있게 하는 것이다. 일단은 아무 기능이 없어도 되기 때문에 매우 간단하게 만들 수 있다. 다음을 따라 해 보자.

>>> class FourCal:
...          pass
...
>>>

우선 대화형 인터프리터에서 pass란 문장만을 포함한 FourCal 클래스를 만든다. 현재 상태에서 FourCal 클래스는 아무 변수나 함수도 포함하지 않지만 우리가 원하는 객체 a를 만들 수 있는 기능은 가지고 있다. 확인해 보자.

(pass는 아무것도 수행하지 않는 문법으로 임시로 코드를 작성할 때 주로 사용한다.)

>>> a = FourCal( )
>>> type(a)
<class '__main__.FourCal'>   <- 객체 a의 타입은 FourCal 클래스이다.

위와 같이 a = FourCal( )로 a 객체를 먼저 만들고 그다음에 type(a)로 a 객체가 어떤 타입인지 알아보았다. 역시 객체 a가 FourCal 클래스의 객체임을 알 수 있다.

 

 

 

객체에 숫자 지정할 수 있게 만들기

하지만 생성된 객체 a는 아직 아무런 기능도 하지 못한다. 이제 더하기.나누기.곱하기.빼기. 등의 기능을 하는 객체를 만들어야 한다. 그런데 이러한 기능을 갖춘 객체를 만들려면 우선 a 객체에 사칙연산을 할 때 사용할 2개의 숫자를 먼저 알려주어야 한다. 다음과 같이 연산을 수행할 대상(4, 2)을 객체에 지정할 수 있게 만들어 보자.

>>> a.setdata(4, 2)

 

위 문장을 수행하려면 다음과 같이 소스 코드를 작성해야 한다.

>>> class FourCal:
...         def setdata(self, first, second):
...               self.first = first
...               self.second = second
...
>>>

앞에서 만든 FourCal 클래스에서 pass 문장을 삭제하고 그 대신 setdata 함수를 만들었다. 클래스 안에 구현된 함수는 다른 말로 메서드(Method)라고 부른다. 앞으로 클래스 내부의 함수는 항상 메서드라고 표현할 테니 메서드라는 용어를 기억해 두자.

일반적인 함수를 만들 때 다음과 같이 작성한다.

def 함수 이름(매개변수):
    수행할 문장
    ...

메서드도 클래스에 포함되어 있다는 점만 제외하면 일반 함수와 다를 것이 없다.

setdata 메서드를 다시 보면 다음과 같다.

def setdata(self, first, second):   <- 1.메서드의 매개변수
    self.first = first               <-
    self.second = second   <- 2.메서드의 수행문

 

 

1. setdata 메서드의 매개변수

setdata 메서드는 매개변수로 self, first, second 3개 입력값을 받는다. 그런데 일반 함수와는 달리 메서드의 첫 번째 매개변수 self는 특별한 의미를 가진다.

다음과 같이 a 객체를 만들고 a 객체를 통해 setdata 메서드를 호출해 보자.

>>> a = FourCal( )
>>> a.setdata(4, 2)

그런데 뭔가 좀 이상하지 않은가? setdata 메서드에는 self, first, second 총 3개의 매개변수가 필요한데 실제로는 a.setdata(4, 2)처럼 2개 값만 전달했다. 왜 그럴까? 그 이유는 a.setdata(4, 2)처럼 호출하면 setdata 메서드의 첫 번째 매개변수 self에는 setdata메서드를 호출한 객체 a가 자동으로 전달되기 때문이다. 다음 그림을 보면 객체를 호출할 때 입력한 값이 메서드에 어떻게 전달되는지 쉽게 이해할 수 있을 것이다.

파이썬 메서드의 첫 번째 매개변수 이름은 관례적으로 self를 사용한다. 객체를 호출할 때 호출한 객체 자신이 전달되기 때문에 self를 사용한 것이다. 물론 self말고 다른 이름을 사용해도 상관없다.

 

 

*메서드의 또 다른 호출 방법

잘 사용하지는 않지만 다음과 같이 클래스를 통해 메서드를 호출하는 것도 가능하다.

>>> a = FourCal( )
>>> FourCal.setdata(a, 4, 2)

위와 같이 '클래스 이름.메서드' 형태로 호출할 때는 객체 a를 첫 번째 매개변수 self에 꼭 전달해 주어야 한다. 반면에 다음처럼 '객체.메서드' 형태로 호출할 때는 self를 반드시 생략해서 호출해야 한다.

>>> a = FourCal( )
>>> a.setdata(4, 2)

 

 

2. setdata 메서드의 수행문

이제 setdata 메서드의 수행문에 대해 알아보자.

def setdata(self, first, second):   <- 1.메서드의 매개변수
    self.first = first              <-
    self.second = second   <- 2.메서드의 수행문

a.setdata(4, 2)처럼 호출하면 setdata 메서드의 매개변수 first, second에는 각각 값 4와 2가 전달되어 setdata 메서드의 수행문은 다음과 같이 해석된다.

self.first = 4
self.second = 2

 

self는 전달된 객체 a이므로 다시 다음과 같이 해석된다.

a.first = 4
a.second = 2

 

a.first = 4 문장이 수행되면 a 객체에 객체변수 frist가 생성되고 값 4가 저장된다. 마찬가지로 a.second = 2 문장이 수행되면 a 객체에 객체변수 second가 생성되고 값 2가 저장된다.

다음과 같이 확인해 보자.

>>> a = FourCal( )
>>> a.setdata(4, 2)
>>> print(a.first)
4
>>> print(a.second)
2

 

a 객체에 객체변수 first와 second가 생성되었음을 확인할 수 있다.

이번에는 다음과 같이 a, b 객체를 만들어 보자.

>>> a = FourCal( )
>>> b = FourCal( )

 

그리고 a 객체의 객체변수 first를 다음과 같이 생성한다.

>>> a.setdata(4, 2)
>>> print(a.first)
4

 

이번에는 b 객체의 객체변수 first를 다음과 같이 생성한다.

>>> b.setdata(3, 7)
>>> print(b.first)
3

 

자, 이제 여러분에게 아주 중요한 질문을 한 가지 하겠다. 위와 같이 진행하면 b 객체의 객체변수 first에는 값 3이 저장된다는 것을 확인할 수 있었다. 그렇다면 a 객체의 first는 3으로 변할까? 아니면 기존 값 4를 유지할까? 다음과 같이 그 결과를 확인해 보자.

>>> print(a.first)
4

 

a 객체의 first 값은 b 객체의 first 값에 영향받지 않고 원래 값을 유지하고 있음을 확인할 수 있었다. 이 예제를 통해 여러분에게 강조하고 싶은 점이 바로 이것이다. 클래스로 만든 객체의 객체변수는 다른 객체의 객체변수에 상관없이 독립적인 값을 유지한다.

 

id 함수를 사용하면 객체변수가 독립적인 값을 유지한다는 점을 좀 더 명확하게 증명해 보일 수 있다. 다시 다음과 같이 따라 해 보자.

>>> a = FourCal( )
>>> b = FourCal( )
>>> a.setdata(4, 2)
>>> b.setdata(3, 7)
>>> id(a.first)   <- a의 first 주소 값을 확인
1839194944
>>> id(b.first)   <- b의 first 주소 값을 확인
1839194928

a 객체의 first 주소 값과 b 객체의 first 주소 값이 서로 다르므로 각각 다른 곳에 그 값이 저장된다는 것을 알 수 있다. 객체변수는 그 객체의 고유 값을 저장할 수 있는 공간이다. 객체 변수는 다른 객체들 영향받지 않고 독립적으로 그 값을 유지한다는 점을 꼭 기억하자. 클래스에서는 이 부분을 이해하는 것이 가장 중요하다.

다음은 현재까지 완성된 FourCal 클래스이다.

>>> class FourCal:
...        def setdata(self, first, second):
...            self.first = first
...            self.second = second
...
>>>

 

지금까지 살펴본 내용이 바로 위 4줄을 설명하기 위한 것이었다. 위에서 설명한 것들이 이해가 되지 않는다면 다시 한 번 읽어 보기 바란다. 이 부분을 이해하지 못하면 다음으로 넘어갈 수 없기 때문이다.

 

 

더하기 기능 만들기

자! 그럼 2개의 숫자 값을 설정해 주었으니 2개의 숫자를 더하는 기능을 방금 만든 클래스에 추가해 보자. 우리는 다음과 같이 더하기 기능을 갖춘 클래스를 만들어야 한다.

>>> a = FourCal( )
>>> a.setdata(4, 2)
>>> print(a.add( ))
6

 

이 연산이 가능하도록 다음과 같이 FourCal 클래스를 만들어 보자

>>> class FourCal:
...        def setdata(self, first, second):
...            self.first = first
...            sefl.second = second
...        def add(self):
...            result = self.first + self.second
...            return sesult
...
>>>

.

새롭게 추가된 것은 add 메서드이다. 이제 클래스를 사용해 보자.

>>> a = FourCal( )
>>> a.setdata(4, 2)

 

위와 같이 호출하면 앞에서 살펴보았듯이 a객체의 first, second 객체변수에는 각각 값 4와 2가 저장될 것이다.

 

이제 add 메서드를 호출해 보자.

>>> print(a.add( ))
>>> 6

 

a.add( )라고 호출하면 add 메서드가 호출되어 값 6이 출력될 것이다. 어떤 과정을 거쳐 값 6이 출력되는지 add 메서드를 따로 떼어 내서 자세히 살펴보자.

def add(self):
    result = self.first + self.second
    return result

 

add 메서드의 매개변수는 self이고 반환 값은 result이다. 반환 값인 result를 계산하는 부분은 다음과 같다.

result = self.first + self.second

 

a.add( )와 같이 a 객체에 의해 add 메서드가 수행되면 add 메서드의 self에는 객체 a가 자동으로 입력되므로 위 내용은 다음과 같이 해석한다.

result = a.first + a.second

 

위 내용은 a.add( ) 메서드 호출 전에 a.setdata(4, 2) 가 먼저 호출되어 a.first = 4, a.second = 2 라고 이미 설정되었기 때문에 다시 다음과 같이 해석한다.

>>> print(a.add( ))
6

 

여기까지 모두 이해한 독자라면 클래스에 대해 80% 이상을 안 것이다. 파이썬의 클래스는 그다지 어렵지 않다.

 

 

곱하기.빼기.나누기 기능 만들기

이번에는 곱하기.빼기.나누기 등을 할 수 있게 프로그램을 만들어 보자.

>>> class FourCal:
...        def setdata(self, first, second):
...            self.first = first
...            self.second = second
...        def add(self):
...            result = self.first + self.second
...            return result
...        def mul(self):
...            result = slef.first * self.second
...            return result
...        def sub(self):
...            result = self.first - self.second
...            return result
...        def div(self):
...            result = self.first / self.second
...            return result
...
>>>

mul, sub div 모두 add 메서드에서 배운 것과 동일한 방법이니 따로 설명하지는 않겠다. 정말로 모든 것이 제대로 동작하는지 확인해 보자.

>>> a = FourCal( )
>>> b = FourCal( )
>>> a.setdata(4, 2)
>>> b.setdata)3, 8)
>>> a.add( )
6
>>> a.mul( )
8
>>> a.sub( )
2
>>> a.div( )
2
>>> b.add( )
11

>>> b.mul( )
24
>>> b.sub( )
-5
>>> b.div( )
0.375

여기까지 우리가 목표로 한 사칙연산 기능을 가진 클래스를 만들어 보았다.

 

 

 

 

 

출처 : "점프 투 파이썬"