본문 바로가기

Python

3. 함수, 입력과 출력 및 파일 읽고 쓰기

함수 및 입력과 출력은 프로그래밍 내에서 매우 중요한 역할을 한다.  백날 프로그램을 만들어도, 입력이 없다면 아무것도 할 수 없다. 우리 앞은 한 치 앞도 모르는데, 어떻게 항상 같은 값만 넣고, 같은 결과만 출력을 받을 수 있을 것 인가? 그래서 우리는 프로그래밍을 할때 '입력'이라는 게 필요한 것이고, 입력이 있으면 '출력'이 있는 법이다. 그게 프로그래밍을 하는 이유이니깐. 함수는 입력 값을 가지고 어떤 일을 수행한 다음에 그 결과물을 내어놓는 것을 편하게 연속적으로 사용하는 방법 중 하나이다. 


파이썬 함수의 예를 설명하자면, sum이라는 함수에 sum을 호출하고, a와 b라는 입력값을 받으면, 자동으로 a+b가 출력이 된다. 수행할 문장 앞에 return이라는 명령어를 사용한 이유는 값을 함수 밖으로 반환하기 위함이다. 만약 함수 안에 return을 사용한 수행할 문장이 두 개가 있으면, return이 적혀져있는 첫 수행할 문장에서 함수는 끝이 난다. 만약 return 후 공백이 적혀있고, 그 밑에 줄에 수행할 문장이 적혀있으면 return에서 이미 함수를 벗어났기 때문에, 공백을 출력한다. 

#함수 문법
def 함수명(입력 인수):
	수행할 문장1
	수행할 문장2

#함수 예
def sum(a,b):
	return a + b

함수를 사용하는 방법은 함수인수를 지정한 후, 함수를 호출하여 값을 출력하는 것이다.

a = 3 #함수인수 지정
b = 4 
c = sum(a,b) #함수호출
print(c)
>> 7

입력값과 결과값에 따라 함수의 형태도 달라진다. 앞전에 설명해준 일반적인 함수는 입력 값이 있고, 그에 따른 결과 값이 있는 함수이다. 허나 입력 값이 없는 함수도 존재한다. 입력 값이 없는 함수는 함수 인수가 존재하지않고, 결과 값이 없는 함수는 return 명령어가 없다. 왜냐하면 함수 인수가 없으면, 어떠한 정보를 입력해도 이 함수와는 상관이 없기때문이다. 그리고 return이 없는 경우는 함수 밖으로 결과 값이 반환이 안되기때문이다. 그래서 결과 값이 없는 함수는 함수(인수1,인수2) 방식으로 호출한다. 

# 입력 값이 없는 함수
def say():
	return 'Hi'

a = say()
print(a)
>> 'Hi'

#결과 값이 없는 함수
def sum(a,b):
	print("%d,%d의 합은 %d입니다."%(a,b,a+b))

sum(3,4)
>> "3,4의 합은 7입니다."

#만약 평소대로 a = sum(3,4), print(a)라고 입력했으면
>>None 

#입력값도 결과값도 없는 함수
def say():
	print('Hi')

say()
>>'Hi'

입력 값이 몇개인지 모를때는 입력 변수 앞에 '*'를 입력한다. 입력 인수가 아닌 입력 변수다.  보통은 이 입력변수안에 'args'를 넣는다. 다른 변수값을 넣어도 괜찮지만, args가 argument의 약자이며, 관례적으로 자주 사용한다. 'args'를 넣으면 함수안에 입력값들이 몇개가 들어가도 상관없다. *args를 사용한뒤로, 입력값들이 튜플안에 들어가기때문이다.  그리고 함수의 결과 값은 언제나 하나이다. 

# *args 문법구조
def 함수명(*입력변수):
	수행할문장

#*args의 예
def sum_mul(choice, *args): #sum_mul이라는 함수 명에 choice라는 함수인수와 *args 합수 변수 입력
    if choice == "sum": #함수인수의 입력 값이 "sum"일 경우
        result = 0 
        for i in args: #입력된 튜플의 있는 숫자들이 i로 하나씩 입력되어
            result += i #result에 하나씩 다 더해짐
    elif choice == "mul": #함수인수의 입력 값이 "mul"일 경우
        result = 1 
        for i in args:
            result = result * i #args안의 있는 숫자들이 모두 곱셈
        
    return result #결과 반환, if와 elif와 같은 위치에 놓아야됨
    
#함수의 결과값은 무조건 하나인 이유
def sum_and_mul(a,b):
	return a+b, a*b

result = sum_and_mul(2,3)
print(result)
>> (5,6) #튜플로 하나에 묶여서 출력. 튜플을 벗어나려면 sum, mul = sum_and_mul(2,3)
#5 6 이런식으로 출력이 된다.

입력 인수에 초깃값을 미리 설정할 수 도 있다. 나이를 두번째 문장에 적지만, 먼저 적은 이유은 age가 두번째나, 세번째에 가있으면, name변수에 나이가 들어가 있거나, address 변수에 나이가 들어가있을 수 있다. 그래서 무조건 초기 입력 변수들은 항상 뒤에 위치 시켜야한다. 

def myself(age, name = '송균석',address = '비밀'): #나이를 제외한 나머지는 지정
    print('나의 이름은 %s입니다.'%name)
    print('나이는 %d살 입니다.'%age)
    print('주소는 %s입니다.'%address)

myself(23)
>>나의 이름은 송균석입니다.
나이는 23살 입니다.
주소는 비밀입니다.

함수 밖에서 선언되는 변수와 함수 안에서 선언되는 변수는 서로 다른 값이다. 왜냐하면 함수 안에서 선언되는 변수는 그 함수만의 변수 이기 때문이다. 허나 함수 안에서 함수 밖의 변수를 사용하는 방법도 있다. 바로 global이라는 변수를 사용하는 것인데, 함수안에 'global 변수' 이렇게 넣으면 된다. global 변수는 전역변수라고도 불리우는데, 외부 변수를 함수에 종속시키는 건 그다지 좋은 함수가 아님으로 최대한 안쓰는 걸 추천한다. 대신 return 명령어를 사용하는 것을 추천한다. 물론 함수 안에 있는 a와 함수 밖에 있는 a라는 변수는 서로 다르지만, a = add_one(a)이라는 명령어를 사용하여 a가 함수의 결과값으로 바뀐다. 

#전역함수 사용
a = 1
def add_one():
    global a #전역함수 선언
    a = a + 1

add_one() 
print(a)

#return을 이용한 방법
a = 1
def add_one(a):
    a += 1
    return a 

a = add_one(a)
print(a)

전에 블로그를 작성할때도 사용했었던 Input에 대해서 설명하려고 한다. 우리가 프로그램을 사용할때 사용자의 행동 혹은 입력이 있어야 그에 알맞은 출력을 컴퓨터는 내놓는다. 이제 입력을 사용할때는 string일 경우 그냥 input()만 사용해도되고, 정수일 경우 int(input())을 사용해서 지정해줘야 정수가 입력이 된다. 혹여나라도 안해주면, 정수가 str로 입력이 되는 대참사가 발생한다. 실수일 경우는 float을 넣어주어야된다. 자료형에 따라 맞춰서 넣어주면된다. 만약 여러 개의 입력이 필요하면 map이라는 객체와, split이라는 명령어를 사용해줘야하한다. 여러 개의 입력을 받으려면 map을 무조건 써줘야된다. map은 리스트의 요소를 지정된 함수로 처리해주는 함수이다. 그리고 split(' ')을 이용한 이유는 입력 값들의 구분을 짓기 위함이다. '10 20 30 40' 처럼 사이에 띄어쓰기를 적용시켜주면 요소에 하나씩 각 변수에 들어간다.

#수학, 사회, 국어, 과학 점수 입력 받기
Math, Social studies, Korean, Science = map(int,input('점수를 입력하세요. : ').split(' '))
print((Math+Social studies + Korean + Science)/4) #평균값구하기

print문으로 할 수 있는 여러가지 역할이 있다. 프린트 안에 있는 문자열들이 큰 따옴표 "" 로 둘러쌓여있으면 +연산을 사용할 수 있다. 그리고 콤마, 를 사용하면 출력시 문자열이 띄어쓰기가 된다. 전에 for문을 설명할때, end =" "에 대해서 설명했었다. 출력시, 문장이 끝나고 다음 문장이 올때, 다음 줄로 안 넘어가고 끝 문자 옆으로 출력하게 된다.

print("Python"+"is"+"fun") #큰 따옴표와 +이용
>> "pythonisfun"

print("life","is","fun") #콤마를 이용한 띄어쓰기
>>"life is fun"

for i in range(5): #end의 예시
	print(i, end=' ')

>>0 1 2 3 4

파이썬에서는 다른 파일을 불러와서 열고, 수정하고, 읽을 수 있다. 전에 친구들과 python을 이용한 deep learning 경연대회를 준비한 적이 있는데, 이걸 생각보다 많이써서 되게 놀랐다. 소의 교배 장면을 캡쳐한 사진들을 불러오는 것이였는데, 처음에 파이썬을 배울 때는 그렇게 중요하다고 생각을 못했는데, 정말 중요한 역할을 맡고 있다. 이걸 보고 공부를 하고 있다면, 자신의 컴퓨터에 한번 실행을 시켜서 느껴보는 게 바람직하다고 생각한다.

 

  • 파일 생성하는 법 : 파일 객체 = open(파일 이름, 파일 열기 모드), 파일 닫기는 필수로 하는 것이 좋다. 
  • 파일의 위치를 지정해서 저장하고 싶다면, open("C:/Python/Newfile.txt","w")라고 지정하면 된다. C드라이브에 있는 파이썬에다가 텍스트파일을 만든다는 의미를 담고 있다.
  • f = open("Newfile.txt", 'w') #open은 파이썬 내장함수다.
    f.close() #파일 닫기​

여기서 파일모드가 무엇인가 생각이 들텐데, 파일을 읽거나 쓰거나 내용을 추가할때 각각 다른 모드를 사용한다. 파일을 읽기만 할때는 'r', 파일에 내용을 쓸 때는 'w', 파일의 마지막에 새로운 내용을 추가할 때는 'a'를 사용한다. read, write, add의 앞 문자라고 생각하면 외우기 쉽다. w 와 a의 역할이 비슷해 보이지만, 해당 파일이 이미 존재할때, w를 사용하면 원래 있던 내용이 모두 사라지고, 파일이 존재하지 않았다면 새로운 파일이 생성된다. 그래서 앞전 예시에서 w를 써서 새로운 파일을 만든 것 이다.

  • 파일을 쓰기 모드로 열어 출력값을 적을 수 있다.
    f = open("C:/Python/새파일.txt","w")
    for i in rnage(1,11):
    	data = "%d번째 줄입니다.\n"%i
    	f.write(data) #data라는 변수객체를 파일에 쓴다는 뜻
    f.close()​
    프로그램 외부에 저장된 파일을 읽는 여러 가지 방법
  • readline() 함수 이용하기; 무한루프를 사용해 모든 라인을 읽을 수 있음
    f = open("C:/Python/새파일.txt","r")
    line = f.readline() #파일의 첫번째 줄 읽기
    print(line) #첫번째 줄 출력
    f.close()
    
    #여기서 파일의 모든 라인을 읽고 싶다면?
    f = open("C:/Python/새파일.txt","r")
    while True: #무한 루프 생성
    	line = f.readline() #계속 파일의 줄 읽기
    	if not line:
    		break #줄 읽기가 끝날시 break
    	print(line)	
    f.close()​
     
  • 입력을 받아서 그 내용을 출력하는 경우,이걸 읽기 대신에 넣으면 된다.물론 쓰기모드나 add모드를 사용해서 늘려야된다.
    while 1: #무한루프 생성
    	data = input()
    if not data: #입력이 없을 경우 break
    	break
    print(data)​
  • raedlines() 함수 이용하기: f.readlines()를 사용하면 파일 안에 있는 내용 들이 리스트 화 되어 한 줄 씩 출력 가능하다.
    f = open("C:/Python/새파일.txt",'r') #읽기 모드로 파일 열기
    lines = f.readlines() 
    for line in lines: 
    	print(line)
    f.close()​
  • add mode 추가 모드 사용하는 법
    f = open("C:/Python/새파일.txt",'a')
    for i in range(11,20):
    	data = "%d번째 줄입니다.\n"%i
     	f.write(data) #add mode로 열었지만 write를 사용해서 내용을 넣어준다.
    f.close()​
  • 앞 전에 설명할때 f.close()는 무조건 써야한다고 했다. 그 이유는 파일을 닫지않고 다시 사용하려면 오류가 나기 때문인데, 이걸 더 편리하게 해주는 with문을 사용하면 f.close()를 사용할 필요가 없다.
    with open("poo.txt",'w') as f:
    	f.write("Hello, It's a beautiful day.") #with block을 벗어나는 순간 파일은 자동으로 닫힌다.​

+f.write()는 무조건 문자열만 된다. 정수형일 경우 str(내용)을 넣어서 문자열로 바꿔줘야한다.

+f.readlines()해서 읽은 애들도 모두 문자열이다. 평균 값을 구하거나 합을 구하는 상황이 생기면 아래와 같이 정수로 전환 후, 합을 구해주면 된다.

sum = 0 
for i in lines:
	i = int(i) #정수형으로 바꿔주기
    sum += i