Python

Python 스터디 5장 - 파이썬 날개 달기 (1)

공대생철이 2023. 6. 30. 22:35
728x90

처음 살펴볼 개념은 클래스 class 이다. 

클래스는 파이썬 뿐만 많은 언어들이 사용하고 있는 키워드이다.

 

먼저 전통의 프로그래밍 언어인 C언어에는 클래스가 없다. 이 말을 굳이 클래스가 없어도 프로그램을 충분히 만들 수 있다는 뜻이다. 파이썬으로 만든 프로그램도 클래스를 사용하지 않고 작성한 것이 매우 많다. 클래스는 프로그램 작성을 위해 꼭 필요한 요소는 아니지만 적재적소에 사용하면 얻을 수 있는 이익이 매우 많다. 

 

result = 0
def add(num):
    global result
    result+=num
    return result

print(add(3))
print(add(4))

add라는 함수를 작성했고 result 값을 유지하기 위해 global을 사용했다.

 

만약 계산기가 2대 필요한 상황이 발생하면 어떻게 해야할까?

result1=0
result2=0

def add1(num):
	//덧셈코드
    
def add2(num):
	//덧셈코드

이런 식으로 별개의 결과값을 선언해주고 함수도 따로 만들어주어야할 것이다. 

그러면 계산기1과 계산기2가 독립적으로 동작한다.

 

하지만 이런 계산기가 10개, 100개 필요하다면 어떨까? 매번 result1, result2... 이러고만 있을 수는 없는 노릇이다.

 

그래서 클래스를 만든다. 

클래스를 비유적으로 말하면 빵틀이다. 그리고 그 빵틀에서 찍어낸 빵들이 객체가 된다.

 

class Calculator:
    def __init__(self):
        self.result=0
    def add(self,num):
        self.result+=num
        return self.result

cal1 = Calculator()
cal2 = Calculator()

print(cal1.add(3))
print(cal2.add(4))

Calculator라는 빵틀에 이름만 다르게 해서 찍어주면 두 개의 객체는 구별되어 동작한다.

 

여기서 새로운 용어가 나온다.

클래스를 활용해서 만든 애를 객체라고 하는데 비슷한 말로 '인스턴스'라는 용어도 있다. 객체와 인스턴스의 차이는 무엇일까?

ca1 = Calculator()로 만든 cal1은 객체이다. 그리고 a 객체는 Calculator의 인스턴스이다. 즉, 인스턴스라는 말은 특정 객체가 어떤 클래스의 객체인지를 관계 위주로 설명할때 사용한다. 'cal1는 인스턴스'보다는 'cal1는 객체', 'cal1은 Calculator의 객체'보다는 'cal1은 Calculator의 인스턴스'라는 표현이 훨씬 잘 어울리는 표현이다.

 

계산기 클래스를 직접 만들면서 배워보자.

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

 

더하기 기능을 하는 add 메서드

빼기 기능을 하는 sub 메서드

곱하기 기능을 하는 mul 메서드

나누기 기능을 하는 div 메서드

연산할 숫자를 설정하는 setdata 메서드

 

여기서 메서드 method라는 단어는 클래스 안에 구현된 함수이다. 클래스 내부의 함수는 항상 메서드라고 표현하니 기억해두자.

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

파이썬 메서드에서 첫번째 매개변수 이름은 관례적으로 self를 사용한다. 객체를 호출할 때 호출한 객체 자신이 전달되기 때문에 self라는 이름을 사용한 것이다.

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

이렇게 하면 a 객체의 first에는 4가 second에는 2가 할당된 것이다. 

그 다음 사칙연산을 하는 메서드들을 하나씩 추가해보자.

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

self를 첫 매개변수로 불러주어 두 숫자의 연산값을 리턴하는 메서드 4개를 작성한 것이다.

 

이 클래스는 치명적인 단점이 있다. setdata로 초깃값을 설정해주지 않으면 무용지물인 클래스다. 그럴 때는 초깃값을 설정하는 메서드를 또 부르는 것보다는 생성자를 구현하는 것이 더 안전하다.

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

생성자 constructor란 객체가 생성될 때 자동으로 호출되는 메서드를 의미한다. __init__이라는 메서드명을 사용하면 이 메서드는 생성자가 된다. 

 

이렇게 생성자가 들어가면 객체를 생성하는 방식이 달라진다.

a=FourCal(4,2)

값을 넣어주지 않으면 __init__이 올바르게 실행되지 않기 때문에 에러를 출력한다. 

그 다음 메서드의 활용은 똑같이 활용하면 된다.

 

클래스는 상속이라는 특성을 가진다.

상속 inheritance란 '물려받다'라는 뜻으로, '재산을 상속받다'할 때랑 같은 의미이다. 클래스에서 이 개념을 접목하면 어떤 클래스를 만들 때 다른 클래스의 기능을 물려받을 수 있게 만드는 것이다. 

FourCal 클래스를 상속하는 클래스를 한번 만들어보자.

class MoreFourCal(FourCal):
    pass

이런 식으로 상속받을 클래스 옆에 소괄호로 상속을 해주면 된다. 그러면 FourCal이 가지고 있던 메서드를 그대로 활용할 수 있게 된다. 

 

상속받은 클래스에 메서드를 확장할 수도 있다.

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

기존의 사칙연산 메서드에 거듭제곱 연산 메서드가 추가되어 총 5개의 연산 메서드를 가지게 된다.

새로운 메서드를 추가할 뿐만 아니라 덮어쓰기도 가능하다. 이를 메서드 오버라이딩이라고 한다.


다음은 모듈이다.

모듈이란 함수나 변수 또는 클래스를 모아 놓은 파이썬 파일이다. 파이썬 프로그램은 여러 개의 모듈이 레고처럼 끼워맞춰져 있다고 해도 과언이 아니다.

 

파이썬 확장 .py로 만든 파이썬 파일은 모두 모듈이다.

 

모듈을 불러오기 위해서는 아래와 같이 사용한다.

import 모듈_이름

또는 모듈 내의 함수만 가져와서 쓰고 싶다면 

from 모듈_이름 import 모듈_함수
//mod1.py
def add(a,b):
    return a+b
    
def sub(a,b):
    retrun a-b

print(add(1,4))
print(sub(4,2))

이런 모듈이 있다고 해볼때 mod1을 import 하면 print문이 실행된다. 하지만 의도가 add, sub 함수만 사용하려 하는 거라면 이런 동작은 방지해야된다. 그래서 다음과 같이 수정해야 한다.

//mod1.py
def add(a,b):
    return a+b
    
def sub(a,b):
    retrun a-b

if __name__ == "__main__":
    print(add(1,4))
    print(sub(4,2))

조건문이 하나 붙었다. 이 조건의 뜻은 직접 이 파일은 실행하는 경우에만 실행한다는 경우다. python3 mod1을 하면 실행되지만 import해서 사용하면 이 파일을 직접 실행하는 것이 아니므로 print는 일어나지 않는다.


다음 살펴볼 개념은 패키지이다.

패키지 packages란 관련 있는 모듈의 집합을 말한다. 패키지는 파이썬 모듈을 계층적(디렉터리 구조)으로 관리할 수 있게 해준다. 

모듈 < 패키지 라는 걸 헷갈리지 말자.

game이라는 패키지 안의 구성이다. gmae 디렉터리가 이 패키지의 루트 디렉터리, graphic, sound라는 서브 디렉터리가 있다.

// echo.py
def echo_test():
    print("echo")

// render.py
def render_test():
    print("render")
    echo_test()

패키지 안에서 다른 폴더의 모듈을 불러와서 실행할 수 있다.

프롬포트에 set 명령어로 PYTHONPATH를 game의 부모 폴더로 설정하면 경로가 game의 부모 폴더를 기준으로 시작하게 된다.

 

import game.sound.echo
game.sound.echo.echo_test()
// echo

이런 식으로 경로를 타고 가서 함수를 실행할 수 있다. 

 

__init__.py는 해당 디렉터리가 패키지의 일부임을 알려주는 역할을 한다. 디렉터리에 __init__.py파일이 없다면 패키지로 인식되지 않는다.

728x90