대망의 첫 번째 글이다.
일단 이 블로그에 쓰는 글의 주요 타겟층은 어느 정도 배운 초보 - 중수쯤에 뒀다. 내가 고수가 아니라서...
그리고 글의 스타일은 너무 코딩 이야기만 하진 않으면서 재미를 약간 추구하고자 한다. 물론 핵심은 꼭 짚을 것이다.
어떤 주제로 글을 써야 할지 많이 고민했다. 그리고 파일 입출력을 첫 주제로 잡았다.
그 이후의 순서는 아마도 백준 안에 있는 단계별로 풀어보기를 적절히 참고해서 따라갈 것이다.
입출력이 왜 중요한가?
너무나 당연한 진리이지만, 프로그램을 짤 때 가장 기초가 되는 부분은 입출력이다.
개발자라면 입력과 출력을 설정할 줄 알아야 하고, 그 입력과 출력 간의 관계를 알고리즘화 하여 코딩해야 한다. 적어도 내가 아는 선에선 그렇다.
따라서 알고리즘을 코딩하기 위해선 입력과 출력을 알아야 하는 건 너무나도 당연하고, 그렇기에 가장 먼저 배워야 한다.
거의 모든 컴퓨터 언어 참고서의 첫 장에 "Hello, World!"를 출력하는 방법부터 써둔 이유가 있다.
아무리 난해한 프로그래밍 언어라 해도 이 언어가 튜링 완전 언어라면 "Hello, World!"는 출력 가능하다.
아래는 개인적으로 좋아하는 난해한 프로그래밍 언어인 엄랭(엄준식랭)을 이용한 "Hello World!"를 출력하는 코드다.
어떻게
엄.......... ..........
식어,,,,,,,,,,,,,,,,,,,,,,,,,,,,ㅋ
식어.ㅋ
식어........ㅋ
식어........ㅋ
식어...........ㅋ
식어,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,ㅋ
식어,,,,,,,,,,,,,ㅋ
식어...........ㅋ
식어..............ㅋ
식어........ㅋ
식어ㅋ
식어,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,ㅋ
이 사람이름이냐ㅋㅋ
들어가기 앞서
먼저 내 PS 코드 스타일을 적는 게 맞을 듯하다. 아래에 서술할 설명은 초보자에겐 조금 어려울 수 있음을 미리 밝힌다.
앞으로 내 코드에서 가장 많이 보일 구절이 바로 이 것이다.
if __name__ == '__main__':
이런 if문을 초장에 쓰는 이유를 말하기 위해선 파이썬이 스크립트 언어로 시작했고, 그렇기에 시작점이 없었으며, 그 때문에 생긴 것이라고 말해야 하는데, 아마도 모르는 사람이 이 문장을 본다면 "스크립트 언어"라는 부분부터 숨이 턱 막힐 가능성이 높다.
간단하게 말하면, 이 파일의 시작점을 여기라고 할 것이라는 선언을 해주는 것이다. C언어를 안다면 main 함수 선언과 비슷하다고만 알아도 될 것이다.
처음으로 파이썬을 접한 사람이라면, 왜 굳이 나눠야 하는지 의문이 들 것이다. 저거 안 써도 알아서 다 해주는데!
맞는 말이다. 하지만 코드가 길어지고 더욱 복잡해지면 시작점을 따로 정해주는 것이 매우 편하다는 것을 깨달을 것이다.
import 하고, 파일 부르고, 그 사이에 함수를 정의하고, 알고리즘을 돌리고, 또 함수를 정의하고, 출력해도 원하는 값을 아마도 줄 것이다.
근데 그렇게 복잡하게 코드를 짜버린다면 남들이 못 읽는 건 뻔할뿐더러, 나중 가면 나 또한 그 코드를 못 읽는 게 문제다. 가독성이 나빠진다는 뜻이다.
그 때문에 난 저 코드를 사용함으로써 가독성을 높이려 했다. 의외로 저 한 줄이 주는 가독성의 차이는 매우 크다.
과장해서 이 가독성의 차이를 말하자면 돼지우리와 그나마 좀 정돈된 내 방의 차이라고 본다.
당장은 잘 모를 수 있겠지만, 앞으로 프로젝트를 만들 때엔 저 코드 구절의 도움을 꼭 받았으면 하는 바람이다.
또한, 나는 PS를 할 때 입력 부분에서도 특정 상황이 아닌 이상 아래의 코드를 전적으로 사용한다.
import sys
if __name__ == '__main__':
a = sys.stdin.readline().rstrip()
아마 대부분의 사람들은 input() 함수를 쓸 것이고, 충분하다 느낄 것이다. 그렇기에 저게 뭔지, 그리고 왜 쓰는지를 물어보는 것은 당연하다.
간단하게 말하면, input()과 sys.stdin.readline()은 같은 입력문이다. 다만 input()은 느리고, sys.stdin.readline()은 빠르다.
PS에서는 일단 빠른 게 최고다. 빠르고 메모리를 덜 잡아먹는 게 가장 중요하다. 실제로 그 빠르다는 C++로 PS 하는 사람들을 봐도 전부 빠른 입출력을 사용한다. 입출력 같은 사소한 것으로 시간을 낭비하지 않기 위함이다.
input() 함수는 출력도 해주면서 동시에 개행 문자('\n')가 나올 때까지 문자(char) 단위로 입력을 받고 문장으로 변환하여 돌려준다.
반면 sys.stdin.readline()은 입력된 한 줄을 그대로 가져온다. 어감 차이로 보일 순 있지만 입력이 많아진다면 이 둘의 속도 차이는 엄청나다. 이에 대해서는 아래에 적어둘 두 백준 문제를 참고하면 좋다.
- [BOJ] 1000번 A+B - [풀이]
- [BOJ] 15552번 빠른 A+B - [풀이]
sys.stdin.readline() 뒤에 붙은 .rstrip()의 의미는 입력받은 문장의 오른쪽에 있는 공백 문자를 지워주는 메서드(method)로, 한 줄을 그대로 가져오는지라 가장 오른쪽에 붙어오는 개행 문자('\n')를 지워주는 역할을 한다.
'\n'이 왜 붙는지를 물어볼 수 있다. 입력을 받기 위해선 키보드 기준으로 Enter 키를 눌러야 한다. 이게 문자로는 '\n'이고, 같은 줄 마지막 부분에 붙어간다고 이해하면 된다.
rstrip() 이외에도 lstrip()과 그냥 strip()도 있으며, 각각 입력받은 문장의 왼쪽, 양쪽에서 지우며, 인자로 아무것도 안 주면 공백 문자를 지워준다. 다만 백준 같은 PS 해결에는 오른쪽에만 개행 문자가 붙기 때문에 rstrip()을 쓴다.
다만 sys.stdin.readline()이 만능인 것은 아닌 게, 빠른 입력문 구절을 EOFError 처리할 때 쓰면 안 된다. 아래의 백준 문제가 대표적이다.
EOFError가 무엇이냐면, End Of File Error, 즉 입력이 더 이상 안 들어와서 내뱉는 에러다.
이 상황에서 sys.stdin.readline()은 EOF 상황에서 EOFError를 발생시키지 않고 빈 문자열을 추가로 입력받는다. 이 때문에 런타임 에러가 발생한다.
즉, sys.stdin.readline()으로는 EOF 처리는 어렵다. 해결할 방법이 있다곤 하지만, 애매하게 알 바엔 모른다 퉁치고 그냥 없다고 보는 게 속 편하다. (확실히 아시는 분이 있다면 댓글 부탁드립니다.)
따라서 EOFError를 처리하기 위해선 EOFError를 처리할 수 있는 input() 함수와 try - except 구문을 같이 사용하는 것이 좋다.
다음 장에선 진짜로 입력과 출력에 대해서 다뤄보고자 한다. 들어가기 전에 미리 알아야 할 것들을 적어야겠다 싶어서 쓴 것이 생각한 분량 이상으로 나와버렸다...
'Python > 파이썬 알고리즘' 카테고리의 다른 글
[파이썬 알고리즘 #5] 반복문 (0) | 2022.08.10 |
---|---|
[파이썬 알고리즘 #4] 조건문 (0) | 2022.08.04 |
[파이썬 알고리즘 #3] 기본 입출력 - 입력 (0) | 2022.07.21 |
[파이썬 알고리즘 #2] 기본 입출력 - 출력 (0) | 2022.07.10 |
[파이썬 알고리즘 Prologue] 아무리 생각해도 나는 코딩 초보다 (0) | 2022.07.07 |
댓글