프로그래밍/PythonBasic

초보를 위한 파이썬 독학 (11): 클래스 기초

자연대생 2023. 7. 12. 17:36

클래스는 복잡하니 예시를 들어 설명드리려고 합니다.

 

필자는 계산기를 만들려고 합니다.

def add(num1, num2):
    return num1 + num2

더하기 코드 하나 정도는 쉽습니다.

사칙연산 코드를 짜보려고 합니다.

 

def add(num1, num2):
    return num1 + num2
    
def sub(num1, num2):
    return num1 - num2
    
def mul(num1, num2):
    return num1 * num2

def div(num1, num2):
    return num1 / num2

코드가 제법(?) 길어졌습니다.

그런데 제가 짜려는 코드 상에서는 필요한 계산기가 여러 대입니다.

그러면 def add1, def add2, def add3, ... 이렇게 코드를 짜야 할까요?

그리고 더하기, 빼기, 곱하기, 나누기를 한번에 묶을 수 있는 방법은 없을까요?

그 방법이 바로 클래스입니다.

 

class Cal():
    def __init__(self, num1, num2):
        self.num1 = num1
        self.num2 = num2

    def add(self):
        return self.num1 + self.num2

    def sub(self):
        return self.num1 - self.num2

    def mul(self):
        return self.num1 * self.num2

    def div(self):
        return self.num1 / self.num2

a = Cal(1, 2)
print(a.add())	# 3
print(a.sub())	# -1
print(a.mul())	# 2
print(a.div())	# 0.5

자세히 살펴볼까요?

 

# 클래스 선언

class Cal():

클래스를 선언하는 방법은 class 키워드 입력 후 이름, 괄호, 콜론을 붙이면 됩니다.

 

# 생성자 __init__()

    def __init__(self, num1, num2):
        self.num1 = num1
        self.num2 = num2

[생성자]라고 부르는 __init__() 메서드입니다.

[메서드]란 클래스에 속해있는 함수를 말합니다.

많은 파이썬 사용자들이 생성자를 사용하여 클래스를 만듭니다.

생성자는 변수에 값을 넣는 과정을 단순화하는 역할을 합니다.

 

첫번째 매개변수로 self를 지정합니다.

[self]란 클래스 자신을 의미합니다.

클래스 내에서 선언된 변수를 self.변수 라고 사용합니다.

self라고 쓰는 것이 관행이 되었기 때문에 따르는 것이 좋습니다.

 

그리고 함수 사용하는 것처럼 매개변수를 입력합니다.

생성자에 매개변수를 설정했다면 객체를 생성할 때 입력받지 못하면 에러가 납니다.

 

# 클래스 내 함수 만들기

    def add(self):
        return self.num1 + self.num2

    def sub(self):
        return self.num1 - self.num2

    def mul(self):
        return self.num1 * self.num2

    def div(self):
        return self.num1 / self.num2

함수에 self를 넣어주는 것은

num1과 num2를 사용하기 위해서 꼭 필요합니다.

변수를 사용할 때에도 self를 써줍니다.

 

# 객체 생성 & 메서드 사용

a = Cal(1, 2)
print(a.add())	# 3
print(a.sub())	# -1
print(a.mul())	# 2
print(a.div())	# 0.5

객체를 생성하고 메서드를 사용하였습니다.

 

a = Cal()
# TypeError: __init__() missing 2 required positional arguments: 'num1' and 'num2'

생성자가 없는 경우 이렇게 객체를 만들어도 됩니다.

하지만 생성자가 있고 거기에 매개변수가 있다면 꼭 입력해주어야 에러가 안 납니다.

스스로의 객체를 의미하는 self는 자동으로 전달되므로 입력하지 않아도 됩니다.

즉, 이 코드에서는 2개만 입력하면 되는 것이죠.

 

그런데 한가지 빠뜨린 게 있습니다.

 

a.div(1, 0)
# ZeroDivisionError: division by zero

0으로 나누기를 하면 오류가 날 수 있다는 점을요.

이를 위해 상속을 씁니다.

 

# 상속, 메서드 오버라이딩

class DivCal(Cal):
    def div(self):
        if self.num2 == 0:
            return "나눌 수 없습니다"
        else:
            return self.num1 / self.num2

이렇게 부모 클래스(상속한 클래스)에 있는 메서드를

동일한 이름으로 다시 만드는 것을 메서드 오버라이딩(method overriding)이라고 합니다.

이렇게 메서드를 오버라이딩하면 부모 클래스의 메서드 대신 오버라이딩한 메서드가 호출됩니다.

 

a = DivCal(1, 0)
print(a.add())  # 1
print(a.sub())  # 1
print(a.mul())  # 0
print(a.div())  # 나눌 수 없습니다

정상 작동하는 것을 볼 수 있습니다.