점프 투 파이썬 - 05

05장 파이썬 날개 달기


 

프로그래밍의 꽃이라 할 수 있는 클래스와 함께 모듈, 예외 처리 및 파이썬 라이브러리에 대해 설명한다.

 

 

[ 클래스 ]

클래스는 왜 필요한가?

프로그래머들이 가장 많이 사용하는 언어 중 하나인 C 언어에는 클래스가 없다. 클래스는 프로그램에서 필수가 아니라는 것이다.

하지만 사용했을 경우 장점이 많기 때문에 자주 사용된다.

 

클래스와 객체

클래스는 과자와 과자 틀을 이용하여 예시를 들 수 있다.

  • 과자 틀 = 클래스
  • 과자 틀로 찍어낸 과자 = 객체

클래스는 과자 틀과 비슷하다. 클래스(class)란 똑같은 무언가를 계속 만들어 낼 수 있는 설계 도면(과자 틀),

객체(object)란 클래스로 만든 피조물(과자 틀로 찍어 낸 과자)을 뜻한다.

 

이러한 객체는 중요한 특징이 하나 있는데, 바로 객체마다 고유한 성격을 지닌다는 것이다.

한 개의 과자에 구멍을 뚫거나 조금 베어먹더라도 다른 과자는 멀쩡한 것처럼 동일한 클래스로 만든 객체들은서로 영향을 전혀 주지 않는다.

 

class Cookie:
	pass

 

이 Cookie 클래스는 아무런 기능도 가지고 있지 않다. 하지만, 이렇게 아무 기능이 없는 클래스도 객체를 생성할 수 있다.

객체를 생성하는 방법은 다음과 같다.

a = Cookie()
b = Cookie()

 

더보기

객체와 인스턴스의 차이

 

클래스로 만든 객체를 '인스턴스'라고도 한다. 그렇다면 객체와 인스턴스의 차이는 무엇일까?

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

 

사칙 연산 클래스 만들기


클래스에서 지원할 기능은 다음과 같다.

a = FourCal()	# 객체 생성

a.setdata(4, 2)	# a에 값 지정
print(a.add())	# 더한 값 리턴
print(a.mul())	# 곱한 값 리턴
print(a.sub())	# 뺀 값 리턴
print(a.div())	# 나눈 값 리턴
6
8
2
2

 

객체에 연산할 숫자 지정하기

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

 

이렇게 클래스 안에 구현된 함수는 다른 말로 메서드(method)라고 한다.

 

 

setdata 메서드의 매개변수

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

 

그런데 조금 이상한 점이 하나 있다. setdata 메서드에서는 self, first, second 총 3개의 매개변수를 입력받도록 되어있으나,

실제로는 2개의 값만 전달한다. 이유는 a.setdata(4, 2)와 같이 호출할 경우, setdata 메서드의 첫 번째 매개변수 self에

setdata 메서드를 호출한 객체 a가 자동으로 전달되기 때문이다.

 

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

물론 다른 이름도 사용이 가능하다.

더보기

메서드를 호출하는 또 다른 방법

클래스를 이용하여 메서드를 호출하는 방법

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

 위와 같이 '클래스명.메서드' 형태로 호출할 때는 객체 a를 첫 번째 매개변수 self 에 꼭 전달해야 한다.

반면 다음처럼 '객체.메서드' 형태로 호출할 때는 self 를 반드시 생략해서 호출해야 한다.

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

setdata 메서드의 수행문

 

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

self.first = 4
self.second = 2

 

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

a.first = 4
a.second = 2

 

 

 

더하기 기능 만들기

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

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

 

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

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

    def add(self):
        result = self.first + self.second
        return result
        
    def mul(self):
        result = self.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

 

 

생성자


생성자(constructor)란 객체가 생성될 때 자동으로 호출되는 메서드를 의미한다.

파이썬 메서드명으로 __init__를 사용하면 이 메서드는 생성자가 된다.

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


    def setdata(self, first, second):
        self.a = a
        self.b = b
    def add(self):
        result = self.first + self.second
        return result
        
    def mul(self):
        result = self.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

 

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

 

__init__ 메서드는 생성자로 인식되어 객체가 생성되는 시점에 자동으로 호출된다.

하지만, a 객체를 [a = FourCal()] 처럼 그냥 생성할 경우 오류가 발생한다.

이유는 생성자의 매개변수 first와 second에 해당하는 값이 전달되지 않았기 때문이다.

이 오류를 해결하려면 first와 second에 해당하는 값을 전달하여 객체를 생성해야 한다.

 

 

클래스의 상속


상속(Inheritance)이란 '물려받다'라는 뜻으로, 어떤 클래스를 만들 때 다른 클래스의 기능을 물려받을 수 있게 만드는 것이다.

앞서 생성한 FourCal 클래스를 상속하는 MoreFourCal 클래스를 만들어보겠다.

class MoreFourCal(FourCal):
	pass

 

클래스를 상속하기 위해서는 다음처럼 클래스 이름 뒤 괄호 안에 상속할 클래스 이름을 넣어주면 된다.

class 클래스_이름(상속할_클래스_이름)

 

그러면 FourCal 클래스의 모든 기능을 사용할 수 있게 된다.

여기서 기능을 추가하면 본래의 FourCal 클래스의 기능과 더불어 MoreFourCal 의 기능도 사용할 수 있는 것이다.

 

상속은 기존 클래스는 그대로 놔둔 채 클래스의 기능을 확장할 때 주로 사용한다.

 

 

메서드 오버라이딩


a = FourCal(4, 0)
print(a.div())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
    result = self.first / self.second
ZeroDivisionError: division by zero

 

 

FourCal 클래스의 객체 a에 값 4와 0을 지정하고 div 메서드를 호출하면 ZeroDivisionError 오류가 발생한다.

이를 해결하기 위해서 FourCal 클래스를 상속하는 SafeFourCal 클래스를 만들어보겠다.

class SafeFourCal(FourCal):
	def div(self):
	if self.second == 0:  # 나누는 값이 0인 경우 0을 리턴하도록 수정
		return 0
	else:
		return self.first / self.second

 

FourCal 클래스에 있는 div 메서드를 동일한 이름으로 다시 작성한 것이다. 이렇게 부모 클래스(상속한 클래스)에 있는 메서드를

동일한 이름으로 다시 만드는 것을 메서드 오버라이딩(method overriding)이라고 한다. 이렇게 메서드를 오버라이딩하면 부모

클래스의 메서드 대신 오버라이딩한 메서드가 호출된다.

 

 

클래스변수


객체변수는 다른 객체들의 영향을 받지 않고 독립적으로 그 값을 유지한다.

클래스변수는 그와 다르게 클래스로 만든 모든 객체에 공유된다.

class Family:
	lastname = "김"

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

Family.lastname = "박"
print(a.lastname)
print(b.lastname)
김
김
박
박

 

이처럼 클래스변수의 값을 변경하면 클래스로 만든 객체의 lastname 값도 모두 변경된다.


 

[ 모듈 ]

모듈이란 함수나 변수 또는 클래스를 모아 놓은 파이썬 파일이다. 모듈은 다른 파이썬 프로그램에서 불러와 사용할 수 있도록 만든 파이썬 파일이라고도 할 수 있다.

 

모듈 만들기


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

 

위와 같이 add와 sub 함수만 있는 파일 mod1.py를 생성하자. 이 파일이 바로 모듈이다.

더보기

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

 

모듈 불러오기


import mod1
print(mod1.add(3, 4))
print(mod1.sub(4, 2))
7
2

 

mod1.py 모듈을 불러오기 위해서는 import mod1 이라고 입력하면 된다.

실수로 import mod1.py 라고 입력하지 않도록 주의해야한다. import는 이미 만들어 놓은 파이썬 모듈을 사용할 수 있게 해 주는 명령어이다. 

  • import는 현재 디렉터리에 있는 파일이나 파이썬 라이브러리가 저장된 디렉터리에 있는 모듈만 불러올 수 있다.
  • 파이썬 라이브러리는 파이썬을 설치할 때 자동으로 설치되는 파이썬 모듈을 말한다.
import 모듈_이름

 

이때, 모듈 이름은 파일에서 확장자를 제거한 이름만을 가리킨다.

때로는 모듈 이름 없이 함수 이름만 쓰고 싶은 경우도 있을 것이다. 이럴 때는 다음과 같이 사용하면 된다.

import 모듈_이름 import 모듈_함수

 

위와 같이 함수를 직접 import하면 모듈 이름을 붙이지 않고 바로 해당 모듈의 함수를 쓸 수 있다.

from mod1 import add
print(add(3, 4))
7

 

하지만 이 방법은 add 함수 하나만 사용할 수 있다.

모든 함수를 불러오기 위해서는 2가지 방법이 있다.

from 모듈_이름 import 모듈_함수1, 모듈_함수2, ...
from mod1 import *

 

여기서 * 문자는 '모든 것' 이라는 뜻인데, 파이썬에서도 같은 의미로 사용한다.

 

 

if __name__ = "__main__": 의 의미


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

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

 

mod1.py 파일을 위와 같이 수정하고 실행하면 아래의 결과가 나온다.

5
2

 

이제 수정한 mod1.py 파일을 import 해보자.

import mod1

 

다른 코드는 아무것도 입력하지 않고 실행을 해보자.

5
7

 

다른 코드는 아무것도 없음에도 결과값을 출력한다. 이러한 일을 방지하기 위해서는 코드를 조금 수정해야 한다.

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

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

 

if __name__ == "__main__" 을 사용하면 직접 이 파일을 실행헀을 때는 __name__ == "__main__" 이 참이 되어 

if 문 다음 문장이 수행된다. 반면 대화형 인터프리터나 다른 파일에서 이 모듈을 불러 사용할 때는 거짓이 되어 수행되지 않는다.

 

 

클래스나 변수 등을 포함한 모듈


# mod2.py
PI = 3.141592

class Math: 
	def solv(self, r): 
		return PI * (r ** 2) 

def add(a, b): 
	return a+b
import mod2
print(mod2.PI)
3.141592

 

이처럼 mod2.py의 변수 값을 mod2.PI 를 통해 불러올 수 있다.

지금까지는 대화형 인터프리터에서 파일이 저장된 디렉터리로 들어가 파이썬을 실행하여 불러오거나,

같은 디렉토리에 다른 파일을 생성하여 모듈을 이용하는 방법을 사용했다.

 

 

다른 디렉터리에 있는 모듈을 불러오는 방법


sys.path.append 사용하기

 

sys 모듈은 파이썬 라이브러리가 설치되어 있는 디렉터리를 확인할 때 사용한다.

sys.path는 파이썬 라이브러리가 설치되어 있는 디렉터리 목록을 보여주며, 이 디렉터리 안에 저장된 파이썬 모듈은

모듈이 저장된 디렉터리로 이동할 필요 없이 바로 불러 사용할 수 있다.이 sys.path에 파이썬 모듈이 있는 디렉터리를 추가한다면 아무 곳에서나 import 하여 사용할 수 있다.

 

PYTHONPATH 환경 변수 사용하기

 

set 명령어를 사용해 PYTHONPATH 환경 변수에 파일이 있는 디렉터리를 설정하면 디렉터리 이동이나 별도의 모듈 추가 작업 없이 디렉터리에 저장된 모듈을 불러와서 사용할 수 있다.

더보기
맥이나 유닉스 환경에서는 set 대신 export 명령을 사용해야 한다.

 

[ 패키지 ]

파이썬에서 패키지 (packages)란 관련 있는 모듈의 집합을 말한다.

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

파이썬 패키지는 디렉터리와 파이썬 모듈로 이루어진다.

 

아래의 내용들은 실습을 위해 [ 점프 투 파이썬 ] - wikidocs의 내용을 변경하지 않고 그대로 따라한 것이다.

패키지 만들기


1. C:/doit 디렉터리 밑에 game 및 기타 서브 디렉터리를 생성하고 .py 파일들을 다음과 같이 만든다.

(C:/doit 디렉터리가 없다면 생성한다.)

C:/doit/game/__init__.py
C:/doit/game/sound/__init__.py
C:/doit/game/sound/echo.py
C:/doit/game/graphic/__init__.py
C:/doit/game/graphic/render.py

 

2. 각 디렉터리에 __init__.py 파일을 만들어 놓고 내용은 입력하지 않는다.

 

3. echo.py 파일의 내용은 다음과 같이 작성한다.

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

 

4. render.py 파일의 내용은 다음과 같이 작성한다. 

# render.py
def render_test():
	print("render")

 

5. game 패키지를 참조할 수 있도록 CMD 창에서 set 명령어로 PYTHONPATH 환경 변수에 C:/doit 디렉터리를 추가하고

파이썬 인터프리터를 실행한다.

 

 

패키지 안의 함수 실행하기


1번째 방법 - echo 모듈을 import 하여 실행한다.

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

 

2번째 방법 - echo 모듈이 있는 디렉터리를 from ... import 하여 실행한다.

>>> exit()
C:\> python
>>> from game.sound import echo
>>> echo.echo_test()
echo

 

3번째 방법 - echo 모듈의 echo_test 함수를 직접 import 하여 실행한다.

>>> from game.sound.echo import echo_test
>>> echo_test()
echo

 

다음과 같이 echo_test 함수를 사용하는 것은 불가능하다.

>>> import game
>>> game.sound.echo.echo_test()
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'sound'
>>> import game.sound.echo.echo_test
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'game.sound.echo.echo_test'; 'game.sound.echo' is not a package

 

  • import game을 수행하면 game 디렉터리의 __init__.py 에 정의한 것만 참조할 수 있다.
  • 도트 연산자(.)를 사용해서 import a.b.c 처럼 import 할 때 가장 마지막 항목인 c는 반드시 모듈 또는 패키지여야만 한다.

 

__init__.py 의 용도


이 파일은 해당 디렉터리가 패키지의 일부임을 알려주는 역할을 한다.

더보기

python 3.3 부터는 없어도 패키지로 인식한다. 하지만 하위 버전 호환을 위해 __init__.py 파일을 생성하는 것이 안전하다.

또한, __init__.py 파일은 패키지와 관련된 설정이나 초기화 코드를 포함할 수 있다.

 

  • 패키지 변수 및 함수 정의
  • 패키지 내 모듈을 미리 import
  • 패키지 초기화

__all__

 

특정 디렉터리의 모듈을 * 을 사용하여 import 할 때는 다음과 같이 해당 디렉터리의 __init__.py 파일에 __all__ 변수를 설정하고 import 할 수 있는 모듈을 정의해주어야 한다.

 

relative 패키지


같은 디렉터리 안에 존재한다면, .. 접근자를 이용하여 import 할 수 있다.

 

접근자 설명
.. 부모 디렉터리
. 현재 디렉터리

 

[ 예외 처리 ]

오류 예외 처리 기법


try-except 문

try:
	...
except [발생오류 [as 오류변수]]:
    	...

 

try 블록 수행 중 오류가 발생하면 except 블록이 수행된다. 하지만 try 블록에서 오류가 발생하지 않는다면 except 블록은 수행되지 않는다.

 

except 구문에서 []를 사용하는는데, 이 기호는 괄호 안의 내용을 생략할 수 있다는 관례적인 표기법이다.

따라서 except 구문은 3가지 방법으로 사용할 수 있다.

 

1. try-except만 쓰는 방법

try:
	...
except:
	...

 

이 경우, 오류의 종류에 상관없이 오류가 발생하면 except 블록을 수행한다.

 

2. 발생 오류만 포함한 except 문

try:
	...
except 발생오류:
	...

 

이 경우, 오류가 발생했을 때 except 문에 미리 정해놓은 오류와 동일한 오류일 경우에만 except 블록을 수행한다.

 

3. 발생 오류와 오류 변수까지 포함한 except 문

try:
	...
except 발생오류 as 오류변수:
	...

 

이 경우는 두 번째 경우에서 오류의 내용까지 알고 싶을 때 사용하는 방법이다.

따라서 오류 변수를 print 시키면 오류 메시지를 확인할 수 있다.

 

 

try-finally 문

finally 절은 try 문 수행 도중 예외 발생 여부에 상관없이 항상 수행된다. 

보통 finally 절은 사용한 리소스를 close 해야할 때 많이 사용한다.

# try_finally.py
try:
	f = open('foo.txt', 'w')
    	# 무언가를 수행한다.

	(... 생략 ...)

finally:
	f.close()  # 중간에 오류가 발생하더라도 무조건 실행된다.

 

파일을 연 후 예외 발생 여부에 상관없이 항상 파일을 닫아 주려고 try-finally 문을 사용하면 된다.

 

 

여러 개의 오류 처리하기

try:
	...
except 발생오류1:
	... 
except 발생오류2:
	...

 

2개 이상의 오류를 동일하게 처리하기 위해서는 위와 같이 괄호를 사용하여 함께 묶어 처리하면 된다.

 

 

try-else 문

try:
	...
except [발생오류 [as 오류변수]]:
	... 
else: # 오류가 없을 경우에만 수행
	...

 

try 문 수행 중 오류가 발생하면 except 절, 오류가 발생하지 않으면 else 절이 수행된다.

 

오류 회피하기


코드를 작성하다 보면 특정 오류가 발생할 경우 그냥 통과시켜야 할 때가 있다.

 

 

오류 일부러 발생시키기


의아하게 생각할 수 있으나, 프로그래밍을 하다 보면 종종 오류를 일부러 발생시켜야 할 경우도 있다.

파이썬은 raise 명령어를 사용해 오류를 강제로 발생시킬 수 있다.

 

예를 들어, 꼭 작성해야 하는 부분이 구현되지 않았을 경우 일부러 오류를 발생시키기 위하여

NotImplementedError를 발생시키기도 한다.

 

예외 만들기


프로그램을 수행하다가 특수한 경우에만 예외 처리를 하려고 종종 예외를 만들어서 사용한다.

 

 


[ 내장 함수, 표준 라이브러리, 외부 라이브러리 ]

위 항목들의 경우, 이미 정리되어 있는 문서를 활용하는 것이 더 적절하다고 판단하여 링크를 첨부한다.

 

05-5 내장 함수

지금까지 파이썬으로 프로그래밍하기 위해 알아야 하는 것들을 대부분 공부했다. 이제 여러분은 원하는 프로그램을 직접 만들 수 있을 것이다. 하지만 그 전에 먼저 여러분이 만들려는 …

wikidocs.net

 

 

05-6 표준 라이브러리

이제 파이썬 프로그래밍 능력을 높여 줄 더 큰 날개를 달아 보자. 전 세계의 파이썬 고수들이 만든 유용한 프로그램을 모아 놓은 것이 바로 **파이썬 표준 라이브러리**이다. ‘라…

wikidocs.net

 

 

05-7 외부 라이브러리

파이썬 설치 시 기본으로 설치되는 라이브러리를 ‘파이썬 표준 라이브러리’라고 한다. 이번에 소개하는 외부 라이브러리는 파이썬 표준 라이브러리가 아니므로 사용하려면 먼저 pip 도…

wikidocs.net

 

 

'Python > ' 카테고리의 다른 글

점프 투 파이썬 - 04  (1) 2023.11.12
점프 투 파이썬 - 03  (1) 2023.11.12
점프 투 파이썬 - 02  (1) 2023.11.09
점프 투 파이썬 - 01  (0) 2023.11.08