파이썬을 배워보자 11일차 - 입출력(input, sys.stdin.readline, print)

0

Python

목록 보기
11/18

점프 투 파이썬 : https://wikidocs.net/book/1
파이썬 기본을 갈고 닦자 : https://wikidocs.net/16031

사용자 입력과 출력

사용자 입력을 받고 출력해주는 기능을 사용해보자

1. 사용자 입력 input

사용자가 입력한 값을 어떤 변수에 대입하고 싶을 때는 input을 사용하면된다.

a = input("입력해주세요 : ")
print(a) # 입력한 값

input() 안에 들어가는 문자열은 어떤 값을 input할지 알려주는 안내문구 같은 것이다.

input()은 한 줄 씩으로만 입력을 받지, 여러 줄로는 입력을 받지 않는다. 즉 한 라인만 쭉 입력받고 나머지는 받지 않는다.

가령, 다음과 같은 입력값이 있다고 하자.

hello
myname is
gyu

input값을 위의 코드에 입력하면 hello만 나온다. 그래서 반복문을 통해 input을 받도록 하자

while True:
    a = input("입력해주세요 : ")
    print(a)

실행시키면 모든 입력을 받을 수 있을 것이다. 입력을 받기가 끊이질 않는다. 이를 위해 우리가 몇개의 값만 받을 것이라고 입력을 받아보자

n = input("몇 번 반복을 하시겠습니까? : ")
while n > 0:
    line = input("입력 : ")
    print(line)
    n -= 1 

다음의 코드를 실행시켜보면 에러가 발생한다.

TypeError: '>' not supported between instances of 'str' and 'int'

왜냐하면, 변수 n이 문자열이기 때문에 정수처럼 다뤄지지 않다는 의미이다.

중요한 것은 input()으로 받는 값들은 모두 문자열이다. 때문에 문자열인 n을 정수로 변환시켜주기 위해서 int를 씌워주어야 한다.

n = int(input("몇 번 반복을 하시겠습니까? : "))
while n > 0:
    line = input("입력 : ")
    print(line)
    n -= 1 

해보면 잘 작동할 것이다. input()에 대해 정리하면 다음과 같다.

  1. input은 한 줄씩 입력을 받는다.
  2. input은 문자열을 입력으로 받기 때문에 다른 타입으로 쓰려면 형변환을 거쳐야 한다.

2. 사용자 입력 sys.stdin.readline()

사실 input()보다 더 빠르게 동작하는 것이 있는데 이것이 바로 sys.stdin.readline()이다.

import sys

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

input과 똑같이 입력을 받는데, 더 빠르다. 때문에 백준과 같은 문제풀이에서 많이 사용된다.

2.1 격자형 입력받기

다음과 같은 격자형 입력값이 있다고 하자

5
0 1 0 1 0
1 0 0 0 0
1 1 1 0 0
0 1 0 1 0
0 0 1 0 0

맨 처음의 입력값인 5는 가로 세로 길이라고 한다면 다음의 입력값을 어떻게 받으면 될까??

import sys

n = int(sys.stdin.readline())
datas = []
while n:
    n -= 1
    line = sys.stdin.readline().rstrip()
    datas.append(line)

print(datas) # ['0 1 0 1 0', '1 0 0 0 0', '1 1 1 0 0', '0 1 0 1 0', '0 0 1 0 0']

다음과 같이 받으면 된다. sys.stdin.readline()은 한 줄 씩으로만 입력을 받는다는 것을 유의하자. 즉, 한글자씩이이 하니라 한 라인씩이다.

rstrip()을 사용하여 오른쪽에 있는 공백을 지웠다. 여기서 rstrip()을 안쓰면 다음과 같이 개행문자가 남아있게 된다.

['0 1 0 1 0\n', '1 0 0 0 0\n', '1 1 1 0 0\n', '0 1 0 1 0\n', '0 0 1 0 0\n']

그런데 사실 원하는 것은 이게 아닐 수 있다. 2차원 배열처럼 입력을 받고 싶을 수 있다. 그럴 땐 split()을 사용하도록 하자

import sys

n = int(sys.stdin.readline())
datas = []
while n:
    n -= 1
    line = sys.stdin.readline().rstrip().split()
    datas.append(line)

print(datas)

결과는 다음과 같다.

[['0', '1', '0', '1', '0'], ['1', '0', '0', '0', '0'], ['1', '1', '1', '0', '0'], ['0', '1', '0', '1', '0'], ['0', '0', '1', '0', '0']]

split()을 사용하니 각 문자들이 공백 기준으로 잘려진 다음 리스트(['0', '1', '0', '1', '0'])에 들어간다. 그리고 이 리스트를 data에 넣는 것이다.

이러면 다음과 같이 2중 for문으로 각 원소에 접근할 수 있다.

for i in range(5):
    for j in range(5):
        print(datas[i][j], end="")
    print()

출력해보면 다음과 같다.

01010
10000
11100
01010
00100

그런데, 사실 지금 datas에 있는 원소들은 모두 문자열이다. 즉, 정수가 아니다. 이를 위해 형변환을 해주어야 하는데 입력 부분에서 해줄 수는 없을까?? 이를 위해 map을 사용해보자

map은 배열이나 리스트의 각 원소를 순회하면서 임의의 함수를 수행하게하여 원소의 값이나 타입을 바꾸어주는 기능을 한다.

기본구조

map(함수, 리스트)

이렇게만 해주면, 내부적으로 리스트를 순회하여 각 원소를 함수의 매개변수로 넣어준다.

values = [1,2,3,4]
a = map(str, values)
print(a) # <map object at 0x000001C67024E0E0>
print(list(a)) # ['1', '2', '3', '4']

다음과 같이 쓴다. 어떻게 된 것이냐면 [1, 2, 3, 4]를 차례대로 순회한다. 먼저 1str(1)을 해주고, 2str(2) 해주고, 3str(3) 해주고, str(4)을 해준다. 그리고 이 값들을 map object에 저장해놓는데, list()```로 씌워주면 리스트가 나온다.

이를 이용해 타입을 바꿔보도록 하자.

import sys

n = int(sys.stdin.readline())
datas = []
while n:
    n -= 1
    line = list(map(int,sys.stdin.readline().rstrip().split()))
    datas.append(line)

print(datas)

결과는 다음과 같다.

[[0, 1, 0, 1, 0], [1, 0, 0, 0, 0], [1, 1, 1, 0, 0], [0, 1, 0, 1, 0], [0, 0, 1, 0, 0]]

깔끔하게 모두 정수형으로 바뀐 것을 볼 수 있다. 이는 split으로 문자 원소들을 모두 나눈 리스트가 나오게되고, 이를 map으로 둘러싸 각 원소마다 int형을 취한 것이다. 그리고 반환된 maplist를 씌워 list로 만든 것이다.

2.2 격자형 입력받기, 공백으로 원소가 구분되지 않을 때

5
01010
10000
11100
01010
00100

다음과 같은 입력은 각 원소들이 공백으로 구분이 안되어있기 때문에 split으로 파싱이 안된다.

그래서 문자열을 list()로 감싸면 하나씩 원소로 나오는 원리를 이용하여 데이터를 저장해보자

print(list("helloworld"))

다음과 같이 문자열인 "helloworld"list에 넣으면 하나하나 원소로 잘라낸다.

출력값은 다음과 같다.

['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']

다음과 같이 말이다. 아주 편하게 좋다.

import sys

n = int(sys.stdin.readline())
datas = []
while n:
    n -= 1
    line = list(sys.stdin.readline().rstrip())
    datas.append(line)

for i in range(5):
    for j in range(5):
        print(datas[i][j], end="")
    print()

그래서 split부분만 떼어내고 list로 넣었다.

01010
10000
11100
01010
00100

깔끔하게 잘 들어간 모습을 볼 수 있다.

이밖에도 다양한 입력값들이 있을텐데 기억나거나 문제풀면서 추가할게 있으면 추가하겠다.

3. 출력

출력은 print이며 이미 많이 다뤄봤으므로 간단하게 다뤄보자

3.1 문자열 띄어쓰기는 콤마로 가능하다.

print("hello" , "world" , "my" , "name" , "is" , "gyu") # hello world my name is gyu

3.2 출력되는 마지막 문자 변경

printkey 매개변수로 end가 있다. end=?으로 출력되는 마지막 값을 설정할 수 있다. 주로 개행문자로 인한 줄바꿈이 싫어 사용한다.

for i in range(10):
    print(i , end=" ") # 0 1 2 3 4 5 6 7 8 9 

다음과 같이 사용할 수 있다.

0개의 댓글