2 분 소요

input과 sys.stdin.readline의 차이점

input은 입력받은 값의 개행(줄바꿈) 문자를 삭제시켜 받아옵니다.

개행 문자를 삭제시킨다는 것은 줄바꿈을 없앤다는 겁니다. 원래 문자열에서 어떤 작업을 취했으니 속도가 느려졌겠죠?

하지만 sys.stdin.readline은 개행 문자를 포함한 값을 받아옵니다. 그러면 input에 비해 속도가 어느정도는 늦어지지 않을 겁니다. 그리고 줄바꿈을 한 정보를 입력받을 때에도 유용합니다.

빠르게 정보를 받아오기 위해서는 sys.stdin.readline을 사용하면 좋습니다.

그래서 알고리즘에서 사용하겠죠? 제한된 자원안에서 목적을 빨리 수행하는 게 알고리즘이니까요.

input은 매개변수로 문자열(String)을 받아, Console에 출력합니다.

Console에 출력을 한다는 것은 문자열을 입력받는 일 외에 하나 더 있다는 것을 알 수 있습니다.

그러면 첫번째 차이점과 같이 속도가 어느 정도는 늦어지겠죠?

하지만 Console에 출력을 해야할 때에는 input을 사용합니다.

💡 속도가 중요한 문제, 특히 알고리즘 문제 같은 경우에서 sys.stdin.readline을 사용합니다.


sys.stdin.readline 사용법

Code

import sys

a = sys.stdin.readline()

input과 sys.stdin.readline의 차이점’에서 설명했듯이 sys.stdin.readline은 개행 문자를 입력받습니다.

그래서 여러줄을 입력받을 수 있기 때문에 ^z를 사용하면 입력받기를 종료해줍니다.

여기서 개행 문자를 삭제하기 위해서 2가지 방식을 사용합니다.

  1. type을 int(정수형)로 바꿔서 ‘\n’ 같은 개행 문자를 받지 못하도록 하기
  2. 개행 문자를 제거해주는 함수 사용하기 (Ex. strip)

Code - type을 정수형으로 변경

import sys
a = int(sys.stdin.readline())

Code - 개행 문자를 제거하는 함수 이용

import sys

a = sys.stdin.readline().strip()

💡 개행 문자가 필요 없다면 위와 같은 방식을 사용해서 sys.stdin.readline를 사용합니다.


sys.stdin.readline로 원하는 만큼만 입력받기

^z를 사용하지 않고 원하는 만큼만 sys.stdin.readline를 사용하여 입력받고 싶다면

처음에 input으로 원하는 줄을 지정해주셔서 for문으로 sys.stdin.readline을 반복해주시면 됩니다.

Code

import sys

l = int(input()) # sys.stdin.readline 사용할 횟수
for i in range(l):
    a = sys.stdin.readline()

💡 input에도 적용할 수 있습니다.

하지만 input은 input을 여러 번 해야 한다면 적용을 하는 게 올바르지,

그냥 2~3 줄을 input으로 받는 코드에서 적용을 하게 된다면 코드 보기가 힘듭니다.

참고로 그런 상황이라면 sys.stdin.readline 사용하는게 효율이 좋습니다.

시간을 줄일 수 있기 때문입니다.


sys.stdin.readline로 한 줄에 여러가지 정수 입력받기

1 2 3 11 22 33​

한 줄에 위와 같이 여러 가지 숫자를 받아야 한다면 아래 코드와 같이 사용해주시면 됩니다.

Code

import sys

a = int(sys.stdin.readline().split()) # int, split 함수 추가

💡 input에도 적용할 수 있습니다.

2667번 단지번호붙이기의 오류 해설

lcr7324   5달 전    1

조금 혼동하신 것 같은데,

input=sys.stdin.readline를 사용하면 런타임 에러 (ValueError)가 발생하며

input=sys.stdin.readline().rstrip을 사용하면 런타임 에러 (IndexError)가 발생합니다.

첫 번째 경우를 먼저 봅시다.

list(map(int, list(sys.stdin.readline()))) 은 다음을 수행합니다.

1) sys.stdin.readline()이 한 줄을 입력받습니다. 예컨대 1001을 입력받았으면, ‘1001\n’이 반환됩니다.

2) list(‘1001\n’) 결과 [‘1’, ‘0’, ‘0’, ‘1’, ‘\n’]이 됩니다. (이 list는 사실 필요가 없습니다. 왜냐하면 map은 iterable을 받아오기만 하면 되는데, str 또한 iterable이기 때문입니다)

3) map을 통해 리스트의 각 원소에 int를 씌워주려고 시도를 합니다만… 마지막 int(‘\n’)이 실패합니다. 여기서 다음의 런타임 에러가 발생합니다.

ValueError: invalid literal for int() with base 10: ‘\n’

두 번째 경우가 아주 재미있는데요, 상상하신 것과 아주 다른 일이 일어납니다.

예컨대, 예제 입력을 따라 맨 처음에 7을 입력했다면, 다음이 순차적으로 수행됩니다.

input = sys.stdin.readline().rstrip에서,

input은 ‘7\n’ 이라는 str object의 built-in method rstrip이 됩니다. 이게 무슨 소리냐면…

1) sys.stdin.readline()을 통해 ‘7\n’ 이라는 str 클래스의 객체가 생성됩니다.

2) 그러면 sys.stdin.readline().rstrip 이라는 표현은 이 ‘7\n’ 이라는 str 클래스 객체의 메소드 함수를 의미합니다.

3) 이걸 input에 저장한 겁니다.

이 시점부터 input()은 이 메소드 함수를 실행하는 것이 되므로, ‘7’을 반환하게 됩니다. 다시 말해, input()은 ‘7’과 사실상 동치입니다. 키보드 입력은 아예 받지도 않습니다!

그래서 n = int(input())에 의해 n에 7이 저장되고,

m.append(list(map(int, list(input()))))는 m.append(list(map(int, list(‘7’))))이 되어 최종적으로 m은 [[7], [7], [7], [7], [7], [7], [7]]이 됩니다.

따라서 밑의 이중 for문에서 y=0, x=1일 때 IndexError가 발생합니다.

의도하신 동작을 수행하려면 input = lambda: sys.stdin.readline().rstrip() 으로 작성하면 됩니다.

2번은 input이 입력 값(문자열)을 저장하는 것이 아니라 “호출하면 항상 특정 값을 반환하는 어떤 함수”를 저장하고 있다고 보아야 합니다.

정확히는 input = sys.stdin.readline().rstrip 이라는 명령을 실행한 순간 다음 두 가지가 연달아 일어납니다.

1) sys.stdin.readline()이 실행됩니다. 즉, 한 줄을 입력받습니다.

2) input은 그 입력받은 문자열에 속한 rstrip 함수를 저장합니다.

언젠가 함수를 변수에 저장하는 것, 그리고 클래스와 객체라는 개념을 공부하시면 정확히 이해하는 데에 도움이 될 것 같습니다.

https://www.acmicpc.net/board/view/102730




참고문헌

[Python] 입력 받기(input VS sys.stdin.readline 차이점) — Xsop의 개발일기