아래 한글을 사용하는 경우 아래 그림과 같은 방식으로 비용을 자동으로 계산할 수 있다.
|
그림 내용: 아래한글의 세로합계 자동계산
여기서는 파이썬을 이용하여 금액에 대한 정보를 추출하여 활용하는 방식을 구현하고자 한다.
txt
라는 확장자를 가진 파일을 순수한 텍스트 파일이라 부른다.
반면에 아래한글 파일, 워드 파일, 엑셀 파일 등은 순수한 텍스트 파일이 아니다.
위 그림에서 볼 수 있듯이 아래한글 파일은 표, 그림 등을 다룰 뿐만 아니라, 수식처리 및 계산 등을 동시에 다룰 수 있다. 반면에 순수한 텍스트 파일은 글자를 보여주는 것 이외에는 어떤 기능도 가지고 있지 않는다.
데이터를 저장하는 경우 보통 순수한 텍스트 파일로 저장한다. 이전 시간에 다룬 웹 상의 정보들도 기본적으로 순수한 텍스트 파일이다. 순수한 텍스트 파일에서 정보를 구하는 여러 방식이 알려져 있으며 오늘 그 중에 한 가지를 배우고자 한다.
def
라는 키워드를 이용하며, 아래 형식을 따른다.
def 함수이름(인자1,..., 인자n):
함수본체
return 리턴값
주의사항:
:
)을 항상 사용해야 함에 주의할 것.예를 들어, 인자 두 개를 입력 받아 합을 리턴하는 함수인 mysum
함수를 다음과
같이 정의한다.
함수의 이름은 임의로 정할 수 있지만 함수의 기능에 맞추어 정해야 한다.
In [1]:
def mysum(a, b):
return a + b
프로그래밍 코드를 저장한 파일에는 코드 이외에 코드와 관련된 주석을 적절하게 포함하고 있어야 한다. 이를 "문서화"라 한다.
문서화는 코드 이상으로 중요하다. 문서화가 제대로 되어있지 않은 경우 코드 개발 및 관리를 매우 어렵게 만든다.
문서화의 기본은 함수에 주석을 추가하는 것이다. 함수정의에 사용되는 주석을 "docstring(문서화 문자열)"이라 부른다.
함수에 주석을 달아주면 help
함수를 이용하여 해당 함수의 역할 및 사용법을 확인할 수 있다.
In [2]:
abs(-3.2)
Out[2]:
In [3]:
help("abs")
보이는 내용을 설명하면 다음과 같다.
1번 줄: abs는 __builtin__
이란 모듈에 정의된 내장 함수이다.
2번~3번 줄: abs(숫자) 형식으로 실행하면 어떤 숫자를 리턴한다. 즉, 입력값과 리턴값의 자료형을 설명하고 있다.
4번 줄: 인자의 절대값을 리턴한다. 즉, 어떤 값을 리턴하는지 설명한다.
In [4]:
def mysum(a, b):
"""
내가 정의한 덧셈이다.
인자 a와 b에 각각 두 숫자를 입력받아 합을 되돌려준다.
"""
return a + b
mysum
함수에 대해 알아보자.
In [5]:
help(mysum)
mysum
함수를 정의할 때 추가한 문서화 문자열이 그대로 출력됨을 확인할 수 있다.
이와같이 문서화 문자열을 잘 활용하면 좀 더 효율적인 코딩을 할 수 있게 된다.
함수를 정의한 후에 사용하려면 호출해야 한다.
함수를 호출한다는 말은 필요한 만큼의 값을 인자로 사용하여 함수를 실행한다는 의미이다. 즉, 함수 호출은 아래 모양의 코드를 실행하는 것이다.
함수이름(인자1,..., 인자n)
In [6]:
x = 2
y = 3
z = mysum(x,y)
In [7]:
print(z)
In [8]:
no_return = print(3)
print()
함수의 리턴값은 None
이다.
In [9]:
print(no_return)
파이썬에서 다루는 값은 모두 자료형을 갖고 있으며, None
의 자료형은 NoneType
이라 부른다.
In [10]:
type(no_return)
Out[10]:
In [11]:
def print42():
print(42)
def return42():
return 42
In [12]:
b = return42()
In [13]:
b
Out[13]:
In [14]:
print(b)
In [15]:
a = print42()
In [16]:
a
In [17]:
print(a)
모듈은 우선 단순한 파이썬 코드를 담고 있는, 확장자가 py
인 파일이다.
그리고 하나의 모듈에는 관련된 일을 처리할 때 사용하는 여러 프로그램 코드들이 포함되어 있다.
주로 함수와 클래스 등이 포함된다.
예를 들어, math
모듈은 sin
, cos
, log
등 수학에서 매우 중요한 역할을 하는 함수들이 정의되어 있다.
그리고 time
모듈에는 sleep
함수 처럼 시간의 활용과 관련된 다양한 함수가 포함되어 있다.
특정 모듈에 포함된 코드(예를 들어, 함수 또는 클래스)를 사용하려면 먼저 해당 모듈을 import
해야 한다.
예를 들어, sin(pi/2)
값을 구하기 위해서는 먼저 math
모듈을 임포트해야 한다.
sin
함수의 정의와 원주율 pi
값의 정의 모두 math
모듈에 포함되어 있다.
주의: 모듈을 임포트하는 여러 방식이 존재한다.
In [18]:
import math
In [19]:
math.pi
Out[19]:
In [20]:
math.sin(math.pi / 2)
Out[20]:
In [21]:
import math as m
In [22]:
m.pi
Out[22]:
In [23]:
m.sin(m.pi / 2)
Out[23]:
모듈에서 원하는 코드만 가져올 수 있다. 이 경우 모듈 이름을 추가로 붙일 필요가 없어진다.
이 방식은 특정 코드를 자주 활용해야 할 경우 추천한다.
In [24]:
from math import sin, pi
In [25]:
pi
Out[25]:
In [26]:
sin(pi/2)
Out[26]:
이 경우 math
모듈에 포함된 다른 코드는 사용할 수 없다.
In [27]:
math.cos(10)
Out[27]:
In [28]:
from math import *
In [29]:
exp(1)
Out[29]:
In [30]:
help("math")
In [31]:
help("math.sqrt")
앞서 abs
함수에서 살펴 보았듯이 2번줄 ~ 4번 줄 내용은 sqrt
함수를 호출하는 방법과
리턴값을 설명하고 있다. (sqrt
함수는 입력된 값의 제곱근을 리턴한다.)
견본답안:
In [32]:
def shopping(shopping_file):
file = open(shopping_file, 'r')
buy_list = file.read()
file.close()
return buy_list
위 코드에서 파일 내용을 읽어드리는 부분은 다음과 같다.
file = open(shopping_file, 'r')
buy_list = file.read()
file.close()
open
함수는 지정된 파일 내용과 함께 파일과 관련된 많은 정보를 불러온다.
주의: 컴퓨터에 저장된 파일은 단순히 파일에 저장된 내용뿐만 아니라, 파일의 생성과 수정, 파일의 크기 등 추가 정보도 함께 포함한다.
따라서, 파일의 내용만을 따로 확인하고자 한다면 read()
메소드를 이용해야 한다.
close()
메소드는 파일 내용을 읽은 후에 더 이상 파일을 필요로 하지 않을 때 사용한다.
그러면, 더 이상 파일 내용을 확인하지 못하게 된다.
주의: open
함수의 리턴 자료형은 좀 특수한 자료형이며 굳이 이름을 알 필요는 없다.
여기서는 read()
와 close()
메소드를 활용할 수 있다는 사실만 기억한다.
shopping
함수를 shopping_list.txt
파일을 인자로 사용하여
호출해 보자.
주의: 여기서는 data
폴더 안에 쇼핑 리스트 파일이 존재한다고 가정한다.
In [33]:
print(shopping("data/shopping_list.txt"))
리턴값의 자료형은 유니코드 문자열이다.
In [34]:
type(shopping("data/shopping_list.txt"))
Out[34]:
이제 문자열의 split
메소드를 활용해서, 쇼핑 목록을 리스트로 작성해보자.
줄을 구분하는 기호는 \n
(역슬래시 + n) 이며, 이를 기준으로 split()
메소드를 호출하면 된다.
In [35]:
buy_list = shopping("data/shopping_list.txt").split("\n")
buy_list
에는 이제 각 줄의 내용을 항목으로 갖는 리스트가 할당된다.
세 줄이 있으므로, buy_list
의 길이는 3이 된다.
주의:
리스트 자료형은 다음 시간에 좀 더 자세히 살펴볼 것이다. 여기서는 자바, C 언어 등에서 배운 리스트 또는 어레이 등의 개념 정도로 이해하면 된다.
In [36]:
print(buy_list)
리스트에 포함된 각각의 항목에 대해 for
반복문을 실행할 수 있다.
아래 코드는 쇼핑 목록의 각 줄을 한 줄씩 출력한다.
앞서 다룬 shopping("shopping_list.txt")
의 리턴값은 파일 내용 전체를 하나의 문자열로 리턴함에 주의하라.
In [37]:
for item in buy_list:
print("===")
print(item)
앞서 배운 range
함수와 인덱스를 활용하여 동일한 일을 수행할 수도 있다.
In [38]:
for i in range(len(buy_list)):
print("===")
print(buy_list[i])
이제 시장을 볼 때 필요한 총 비용이 얼마인지 계산할 수 있다. 먼저 각 물품의 비용을 확인해 볼 수 있는데, 그러려면 각 줄이 하나의 문자열이면서 물품, 개수, 가격이 스페이스로 구분되어 있다는 정보를 활용하면 된다.
즉, split()
메소드를 다시 한 번 활용한다.
In [39]:
for item in buy_list:
each_item = item.split()
print(each_item[0], each_item[1], "개의 가격은", each_item[2], "원 입니다.")
이제 총 비용을 계산할 수 있다.
In [40]:
total = 0
for item in buy_list:
total = total + int(item.split()[2])
print("총 비용은", total, "입니다.")
견본답안:
먼저 앞서 정의된 shopping
함수를 그대로 사용하면서 shopping_list.txt
파일의 경로를
틀리게 사용하면 아래처럼 오류가 발생한다.
In [41]:
shopping("shopping_list.txt")
오류가 발생하면서 실행이 멈춘 이유를 설명하기는 하지만 부가 설명이 필요한 경우에는 아래와 같이 예외 처리 기능을 추가하는 것이 좋다.
In [42]:
def shopping(shopping_file):
try:
file = open(shopping_file, 'r')
buy_list = file.read()
file.close()
return buy_list
except FileNotFoundError:
raise FileNotFoundError("해당 파일의 이름 또는 경로를 확인하세요.")
이제 다시 shopping_list.txt
파일의 경로를 틀리게 사용하면 다음과 같이 예외 처리가 실행된다.
In [43]:
shopping("shopping_list.txt")
견본답안:
In [44]:
def shopping_amount(shopping_file):
buy_list = shopping(shopping_file).split('\n')
total = 0
for item in buy_list:
total = total + int(item.split()[2])
return total
In [45]:
shopping_amount("data/shopping_list.txt")
Out[45]:
견본답안 1:
In [46]:
def shopping_item(shopping_file, items):
buy_list = shopping(shopping_file).split('\n')
total = 0
if 'bread' in items.lower():
total += int(buy_list[0].split()[2])
if 'tomato' in items.lower():
total += int(buy_list[1].split()[2])
if 'cola' in items.lower():
total += int(buy_list[2].split()[2])
return total
In [48]:
item = input("Bread, Tomato, Cola 중 살 품목을 적어주세요: ")
print(shopping_item("data/shopping_list.txt", item))
견본답안 2: 내장함수인 sum
을 활용할 수 있다. sum
에 대한 설명은 여기를 참조하면 된다.
In [49]:
def shopping_item(shopping_file, items):
buy_list = shopping(shopping_file).split('\n')
price_list = []
if 'bread' in items.lower():
price_list.append(int(buy_list[0].split()[2]))
if 'tomato' in items.lower():
price_list.append(int(buy_list[1].split()[2]))
if 'cola' in items.lower():
price_list.append(int(buy_list[2].split()[2]))
return sum(price_list)
In [50]:
item = input("Bread, Tomato, Cola 중 살 품목을 적어주세요: ")
print(shopping_item("data/shopping_list.txt", item))
견본답안:
In [51]:
def shopping_amount_n(shopping_file, n):
buy_list = shopping(shopping_file).split('\n')
total = 0
for i in range(len(buy_list)):
total += int(buy_list[i].split()[2]) * n[i]
return total
In [52]:
while True:
try:
n = list(map(int, input("Bread, Tomato, Cola을 구매할 수량을 차례대로 입력하세요: ").split(', ')))
break
except ValueError:
print("정수로 입력하세요.")
print(shopping_amount_n("data/shopping_list.txt", n))