클래스

honeyricecake·2022년 6월 30일
0

파이썬

목록 보기
17/26

클래스와 객체

클래스란 똑같은 무엇인가를 계속해서 만들어낼 수 있는 설계 도면이고 (과자 틀),
과자 틀에 의해서 만들어진 과자는 객체(object)이다.

클래스로 만든 객체에는 중요한 특징이 있다.
바로 객체마다 고유한 성격을 가진다는 것이다. 과자 틀로 만든 과자에 구멍을 뚫거나 조금 베어먹더라도 다른 과자에는 아무 영향이 없는 것과 마찬가지로 동일한 클래스로 만든 객체들은 서로 전혀 영향을 주지 않는다.

다음은 파이썬 클래스의 가장 간단한 예이다.

class Cookie:
	pass

위의 클래스는 아무 기능도 갖고 있지 않은 껍질뿐인 클래스이다. 하지만 이렇게 껍질 뿐인 클래스도 객체를 생성하는 기능이 있다.

"과자 틀"로 "과자"를 만드는 것처럼 말이다.

객체는 클래스로 만들며 1개의 클래스는 무수히 많은 객체를 만들어 낼 수 있다.

위에서 만든 Cookie 클래스의 객체를 만드는 방법은 다음과 같다.

a = Cookie()
b = Cookie()

Cookie()의 결괏값(생성된 객체의 레퍼런스)을 돌려받은 a,b가 바로 객체이다. 마치 함수를 사용해서 그 결괏값을 돌려받는 모습과 비슷하다.

Tip.객체와 인스턴스의 차이

a = Cookie() 이렇게 만든 a는 객체이다. 그리고 a 객체는 Cookie의 인스턴스이다.
즉, 인스턴스라는 말은 특정 객체(a)가 어떤 클래스의 객체인지를 관계 위주로 설명할 때 사용한다.

사칙연산 클래스 만들기

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

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

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

a = FourCal() -> 객체 생성
a.setdata(4, 2) -> 숫자 4와 2를 a에 지정
print(a.add()) -> 두 수를 더한 결과 리턴

비슷하게 mul, sud, div도 구현하는 것이 우리의 목표이다.

  1. 클래스 구조 만들기
class FourCal:
    pass

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

class FourCal:
    pass

a = FourCal()
print(type(a))

<class '__main__.FourCal'> 이 출력된다.
즉, 객체 a가 FourCal클래스의 객체임을 알 수 있다.

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

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

(1) setdata 메서드의 매개변수

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

이런 식으로 객체를 호출할 때 객체 자신이 첫번째 매개변수로 전달되어 관례적으로 클래스 메서드의 첫번째 매개변수 이름으 self를 사용한다.

잘 사용하지 않지만 다음과 같이 클래스를 통해 메소드를 호출할 수도 있다.

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

(2) setdata 메서드의 수행문

self.first = first
self.second = second

는 a.setdata(4,2)처럼 호출하면
a.first = 4
a.fisrt = 2와 같아진다.

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

(객체에 생성되는 객체만의 변수를 객체변수라고 부른다.)

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

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

4 2가 출력되는 것을 볼 수 있다

계산기 기능 만들기

더하기 기능은 다음과 같이 만들 수 이싿.

class FourCal:

    def setdata(self, first, second):
        self.first = first
        self.second = second

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

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

6이 출력되는 것을 볼 수 있다.

나머지 메서드 들도 동일한 방법으로 구현할 수있다.

class FourCal:

    def setdata(self, first, second):
        self.first = first
        self.second = second

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

    def sub(self):
        result = self.first - self.second
        return result

    def mul(self):
        result = self.first * self.second
        return result

    def div(self):
        result = self.first / self.second
        return result

a = FourCal()

a.setdata(4,2)

print(a.add())
print(a.sub())
print(a.mul())
print(a.div())

6
2
8
2.0 이 출력되는 것을 볼 수 있다.

생성자 (Constructor)

a = FourCal()
a.add() 를 하면 에러가 발생한다.

왜냐하면 a에 fisrt와 second 변수를 생성하지 않았기 때문이다.

따라서 객체에 초깃값을 반드시 설정해야할 필요가 있을 때는 setdata같은 메서드 보다는 생성자를 구현하는 것이 안전한 방법이다.

생성자란 객체를 생성할 때 자동으로 호출되는 메서드를 의미한다.

class FourCal:

    def __init__(self,first,second):
        self.first = first
        self.second = second

    def setdata(self, first, second):
        self.first = first
        self.second = second

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

    def sub(self):
        result = self.first - self.second
        return result

    def mul(self):
        result = self.first * self.second
        return result

    def div(self):
        result = self.first / self.second
        return result

a = FourCal(4,2)

print(a.add())
print(a.sub())
print(a.mul())
print(a.div())

6
2
8
2.0
이 정상적으로 출력된다.

클래스의 상속

class MoreFourCal(FourCal):
    pass

FourCal 클래스를 상속했으므로 FourCal 클래스의 모든 기능을 사용할 수 있어야 한다.

이 MoreFourCal 함수에 a의 b제곱을 계산하는 함수를 추가해보자.

class MoreFourCal(FourCal):
    def pow(self):
        result = self.first ** self.second
        return result

메서드 오버라이딩

FourCal 클래스를 다음과 같이 실행해보자.

a = FourCal(4,0)
a.div()

FourCal 클래스의 객체 a에 4와 0 값을 설정하고 div메서드가 호출하면 4를 0으로 나누려고 하기 때문에 ZeroDivisionError 오류가 발생한다. 하지만 0으로 나눌 때 오류가 아닌 0을 돌려주도록 만들고 싶다면 어떻게 해야할까?

class SafeFourCal(FourCal):
    def div(self):
        if(self.second == 0):
            return 0
        else:
            return self.first/self.second

SafeFourCal 클래스는 FourCal 클래스에 있는 div 메서드를 동일한 이름으로 다시 작성하였다. 이렇게 부모 클래스(상속한 클래스)에 있는 메서드를 동일한 이름으로 다시 만드는 것을 메서드 오버라이딩(덮어쓰기) 이라고 한다.
이렇게 메서드를 오버라이딩하면 부모클래스의 메서드 대신 오버라이딩한 메서드가 호출된다.

SafeFourCal클래스에 오버라이딩한 div 메서드는 나누는 값이 0인 경우에는 0을 돌려주도록 수정했다. 이제 다시 위에서 수행한 예제를 FourCal클래스 대신 SafeFourCal 클래스를 사용하여 수행해 보자.

a = SafeFourCal(4,0)
a.div()

0이 출력된다.

클래스 변수

객체 변수는 다른 객체들에 영향받지 않고 독립적으로 그 값을 유지한다는 점을 이미 알아보았다.

이번에는 객체 변수와는 성격이 다른 클래스 변수에 대해 알아보자.

class Family:
	lastname = "김"

이렇게 클래스에서 선언한 lastname이 바로 클래스 변수이다.
클래스 변수는 모든 객체들이 공유하는 변수이다.

class Family:
    lastname = "김"

a = Family()
b = Family()

print(a.lastname)
print(b.lastname)

a.lastname = "박"

print(a.lastname)
print(b.lastname)
print(Family.lastname)





이 출력됨을 볼 수 있다.

classname은 현재 클래스 변수이나
a.lastname = "박"
을 통해 객체변수 lastname을 만들 수 있고 이가 우선됨을 볼 수 있다.

(객체를 호출하여 변수 생성한 것은 객체 내의 객체 변수)

0개의 댓글