Skip to content
This page has been auto-translated and may contain errors.View in English

출력과 입력

docs.scrimba.com

처음 작성하는 코드부터 사용하게 될 두 가지 도구: print()는 터미널에 값을 표시하고, input()은 사용자로부터 텍스트를 받습니다. 간단하지만, 이들의 동작 방식을 이해하면 초기에 마주칠 수 있는 여러 문제를 피할 수 있습니다.

print()input()은 Python의 표준 터미널 I/O 함수입니다. 둘 다 처음 보이는 것보다 설정 옵션이 많습니다. print()는 값을 결합하는 방식과 출력이 끝나는 지점을 제어하는 인자를 받습니다. input()은 항상 문자열을 반환하므로, 사용자로부터 오는 모든 값을 어떻게 처리할지를 결정합니다.

내부적으로 print()sys.stdout에 쓰고 input()sys.stdin에서 읽습니다(터미널이 연결된 표준 출력 및 입력 스트림). 둘 다 텍스트만 다루며, 출력은 기본적으로 버퍼됩니다: Python은 출력을 일시적으로 보관했다가 한 문자씩이 아닌 묶음으로 씁니다. 실제 프로그램에서 중요한 두 가지 결과가 있습니다: 출력이 에러와 다른 스트림으로 이동합니다(stdout 대 stderr), 그리고 필요할 때 출력이 즉시 나타나도록 그 버퍼를 강제로 플러시할 수 있습니다.

Python이 코드를 실행하는 방식

Python은 코드를 위에서 아래로, 한 번에 한 줄씩, 당신이 작성한 순서 그대로 실행합니다. 건너뛰는 일은 없습니다. 작성한 순서가 실행 순서입니다. 항상.

python
city = "서울"
print(city)
print("인구: 1,000만 명")

먼저 city가 할당됩니다. 첫 번째 print가 실행됩니다. 두 번째 print가 실행됩니다. 매번 그 순서대로입니다.

이것이 중요한 이유는 변수를 할당하기 전에 사용할 수 없기 때문입니다. Python이 아직 그것을 보지 못했고 에러를 발생시킵니다:

python
print(country)   # NameError: country가 아직 정의되지 않음
country = "일본"

프로그램이 커질 때 이를 기억하세요: 사용하는 모든 것은 사용하기 전에 정의되어야 합니다.

Python은 **순차 실행**을 사용합니다: 각 문은 만날 때 평가되며, 파일의 단일 위에서 아래로의 통과에서 일어납니다. 전체 파일의 사전 스캔은 없습니다. 이름을 할당하기 전에 참조하면 정확히 그 줄에서 NameError가 발생합니다.

python
city = "서울"
print(city)             # 동작: city가 이미 바인딩됨
print(country)          # NameError: 아직 할당되지 않음
country = "일본"

규칙: 의존성은 그것을 사용하는 줄 이전에 정의되어야 합니다.

Python은 파일을 단일 위에서 아래로의 통과로 실행하며, 파일을 처음 읽을 때가 아니라 그 줄이 실제로 실행될 때에만 이름을 찾습니다. 이것이 누락된 이름이 저장하는 즉시가 아니라 런타임에 NameError가 되는 이유입니다. 호이스팅은 없습니다(JavaScript가 var 선언을 조용히 범위의 최상단으로 이동하는 방식처럼). 이름은 할당되는 순간에 존재하며, 그 이전의 모든 사용은 에러를 발생시킵니다.

python
print(country)   # 런타임에 NameError, 구문 에러 아님
country = "일본"
JunoPython이 코드를 실행하는 방식 Python은 파일을 위에서 아래로, 한 번에 한 줄씩, 작성한 순서대로 읽습니다. 모두를 일단 넘어야 할 것: 이름은 그것을 사용하는 줄 이전에 존재해야 하거나 NameError가 발생합니다. 건너뛸 수 없고, 파일을 먼저 읽지 않습니다.
JunoPython이 코드를 실행하는 방식 위에서 아래로, 한 번의 통과, 순서대로. 이름은 그것을 사용하는 모든 줄 이전에 할당되어야 하거나 그 정확한 줄에서 NameError가 발생합니다. 파일의 사전 스캔 없음.
JunoPython이 코드를 실행하는 방식 한 번의 위에서 아래로의 통과, 각 줄이 실행될 때 이름을 찾음. 할당되기 전에 이름을 사용하면 구문 에러가 아닌 런타임에 NameError가 발생합니다. Python은 호이스팅하지 않으며 전방 선언이 없으므로, 순서가 정말 중요합니다.

출력 인쇄하기

print()는 Python이 당신과 대화하는 방식입니다. 모든 값을 전달하면 그 값을 표시합니다. 자동으로 무엇이든 텍스트로 변환합니다.

print()는 각 인자를 str()을 통해 문자열로 변환하고, 구분자(기본적으로 공백)로 결합한 후, 표준 출력에 줄바꿈이 뒤따르도록 결과를 씁니다. 기본값을 이해하면 선택적 인자가 더 예측 가능합니다.

print()의 전체 서명은 print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)입니다. *objects 수집기는 원하는 개수의 위치 인자를 받고 각각에 str()을 호출합니다. sepend는 형식을 제어하고, file은 출력을 모든 쓰기 가능한 스트림으로 리다이렉트하며, flush는 버퍼를 즉시 비웁니다.

python
print("Hello")    # Hello
print(42)         # 42
print(3.14)       # 3.14
print(True)       # True

여러 값

쉼표로 구분하여 한 번에 여러 값을 인쇄할 수 있습니다. Python은 기본적으로 그들 사이에 공백을 넣습니다. sep으로 구분자를 변경하세요:

여러 위치 인자는 각각 str()으로 개별 변환되고, sep으로 결합됩니다. 기본 sep은 단일 공백입니다. 이를 재정의하면 문자열 연결 없이 형식이 지정된 출력을 만들 수 있습니다:

print()는 하나의 문자열을 만들어 쓰지 않습니다. 각 인자를 차례로 스트림에 씁니다(각각에 str() 호출), sep과 함께 그리고 end 마지막에. 이러한 쓰기가 잠긴 단일 작업이 아닌 하나씩 발생하므로, 동시에 실행되는 두 print() 호출(다른 스레드에서)은 출력을 인터리브할 수 있습니다. 이것이 중요할 때, 하나의 문자열을 만들고 한 번만 인쇄하세요. 일상 사용의 경우, sep을 재정의하는 것은 여전히 손으로 문자열을 붙이는 것을 이깁니다:

python
name = "민준"
age = 28
print(name, age)                        # 민준 28
print("Name:", name)                    # Name: 민준
print("2024", "01", "15", sep="-")     # 2024-01-15
print("a", "b", "c", sep=", ")         # a, b, c

줄 끝 제어하기

print() 호출은 기본적으로 줄바꿈으로 끝나므로, 다음 출력은 새 줄에서 시작합니다. end로 이를 변경하세요. end=""를 설정하면 다음 print가 같은 줄에서 계속됩니다:

end 매개변수는 기본 줄바꿈을 바꿉니다. 줄바꿈을 억제하려면 ""로, 같은 줄에 공백으로 머물려면 " "로, 또는 다른 문자열로 설정하세요. sep과 함께, 대부분의 출력 형식을 손으로 문자열을 만들지 않고 생성할 수 있습니다:

sepend는 키워드 전용입니다(이름으로 전달하며, end=""처럼, 절대 위치로 아님). 기본값은 공백과 줄바꿈입니다. end=""는 부분 줄을 인쇄하고 다음 호출이 이를 계속하도록 하는 표준 방식입니다. 진행 표시기나 실시간 로그처럼 나타날 때 출력이 필요한 경우, 줄바꿈이나 버퍼가 찰 때까지 기다리지 않고 Python이 즉시 쓰도록 flush=True를 추가하세요.

python
print("Loading", end="")
print("...")
# Loading...

print("one", end=" | ")
print("two", end=" | ")
print("three")
# one | two | three
Juno출력 인쇄하기print()는 제공하는 모든 것을 텍스트로 바꾸고 표시합니다. 쉼표로 구분된 여러 것을 전달하고 그들 사이의 공백을 얻으며, sep으로 변경하세요. 모든 print는 끝에 새 줄로 떨어집니다; end=""는 다음 줄을 같은 줄에 유지합니다.
Juno출력 인쇄하기print()는 각 인자에서 str()을 실행하고, sep(기본적으로 공백)으로 결합하고, end(기본적으로 줄바꿈)로 마칩니다. 문자열을 붙이지 않고 형식을 만들려면 둘 중 하나를 재정의하세요.
Juno출력 인쇄하기print()는 각 인자를 str()을 통해 쓰고, 사이에 sep과 마지막에 end를 사용하며, 둘 다 키워드 전용입니다. 줄을 계속하려면 end=""에, 출력이 바로 나타나야 할 때는 flush=True에 손을 뻗으세요.

f-string으로 출력 형식 지정하기

메시지를 만드는 가장 깨끗한 방법은 f-string입니다. 여는 따옴표 앞에 f를 놓고, 모든 변수나 식을 중괄호로 감싸세요. Python이 런타임에 채웁니다. 모든 값, 계산, 또는 메서드 호출을 {}안에 넣을 수 있습니다.

f-string은 런타임에 {}안의 모든 식을 평가하고 결과를 문자열로 포함합니다. 값 뒤의 콜론은 형식 지정자를 도입합니다: 소수 자릿수, 정렬, 수 형식을 제어하는 간단한 구문. 이들은 연결보다 빠르고 더 읽기 쉬우며, 명시적인 str() 호출이 필요하지 않습니다.

f-string의 각 {}는 결국 format(value, spec)을 호출하고, 값의 자신의 __format__ 메서드(Python이 값을 형식하기 위해 호출하는 던더, 더블 언더스코어 메서드)에 넘깁니다. 따라서 모든 클래스는 __format__을 정의하여 f-string 내부에서 어떻게 보일지 결정할 수 있습니다. 변환 플래그 !r, !s, !a는 먼저 값에 repr(), str(), ascii()를 실행합니다; !r은 디버깅을 위해 기억할 것입니다. 왜냐하면 코드에 입력하는 방식(따옴표, 이스케이프 등)으로 값을 보여주므로, 아래 실습에서 보여집니다.

python
name = "민준"
score = 980

# 연결: 어색하며, 수 변환을 위해 str() 필요
print("Player: " + name + ", Score: " + str(score))

# f-string: 읽기 쉽고, 수동 변환 없음
print(f"Player: {name}, Score: {score}")

{} 안에 모든 식을 넣을 수 있습니다: 산술, 메서드 호출(.upper() 같은, Strings 장에서 완전히 다룸), 형식 지정자:

python
price = 49.99
tax = 0.2
total = price * (1 + tax)

print(f"Total: {total:.2f}")          # Total: 59.99
print(f"Name: {name.upper()}")        # Name: 민준
print(f"2 + 2 = {2 + 2}")             # 2 + 2 = 4

: 뒤의 형식 지정자는 값이 표시되는 방식을 제어합니다:

python
ratio = 0.8765
count = 1234567
label = "revenue"

print(f"{ratio:.1%}")       # 87.6%
print(f"{count:,}")         # 1,234,567
print(f"{label:>12}")       # "     revenue"

:.2f는 "소수 두 자리"를 의미합니다. 가격과 측정에 끊임없이 사용합니다. 다른 모든 것은 필요할 때 그곳에 있습니다. 주요 것: 변수 이름뿐 아니라 모든 것이 {}안에 갈 수 있습니다.

:.2f:.0%는 대부분의 형식 지정 필요를 다룹니다. 정렬 지정자(>, <, ^)와 너비는 깔끔한 표 형태의 출력을 생성합니다. 일반적인 패턴은 {value:[align][width][.precision][type]}입니다. 한 번 부분을 인식하면, 모든 조합을 암기할 필요 없이 모든 지정자가 읽기 쉽습니다.

같은 지정자도 다른 유형에 다른 의미를 가질 수 있습니다. 왜냐하면 각 유형이 자신을 형식하기 때문입니다. f"{'hi':5}"는 텍스트를 오른쪽에 패딩합니다(텍스트는 기본적으로 왼쪽 정렬) 반면 f"{42:5}"는 왼쪽에 패딩합니다(숫자는 오른쪽 정렬): 같은 :5, 반대 결과. 각 내장 유형은 이 형식 미니 언어에 대해 자신의 규칙을 갖고, 커스텀 클래스는 __format__을 정의하여 자신을 설정합니다.

Junof-string으로 출력 형식 지정하기 여는 따옴표 앞에 f를 놓고 아무 것이든 {}로 감싸세요: 변수, 합, 심지어 메서드 호출. 콜론이 형식을 추가하고, :.2f처럼 소수 두 자리. +로 문자열을 붙이는 것보다 훨씬 깨끗합니다.
Junof-string으로 출력 형식 지정하기f"..."는 모든 식의 결과를 문자열에 직접 떨어뜨리고, str() 없음. 콜론 뒤에 형식 지정자가 옵니다: :.2f, :,, :>12 등. 연결보다 깨끗하고 빠릅니다.
Junof-string으로 출력 형식 지정하기 각 `{}`는 값의 자신의 `__format__`을 호출하므로, 콜론 뒤의 지정자는 그 유형이 결정하는 것을 의미합니다. `!r`은 기억할 것: 코드에 입력하는 방식으로 값을 보여주며, 이는 디버깅할 때 후행 공백 및 다른 보이지 않는 쓰레기를 눈에 띄게 만듭니다.

사용자로부터 입력 받기

input()은 프로그램을 일시 중지하고 사용자가 뭔가 입력할 때까지 기다립니다. 사용자가 입력한 것(그리고 Enter를 누른 것)이 반환 값으로 돌아옵니다. 괄호 안의 문자열은 사용자가 보는 프롬프트입니다.

python
name = input("What's your name? ")
print(f"Hello, {name}!")

input()사용자가 입력한 것이 무엇이든 항상 문자열을 반환합니다. 42를 입력하면 숫자 42가 아닌 "42"를 얻습니다. 이를 사용하여 산술을 하려면 명시적으로 변환하세요:

python
age = int(input("How old are you? "))
print(f"In ten years you'll be {age + 10}.")

사용자가 변환할 수 없는 것을 입력하면 어떻게 될까요? Python은 ValueError를 발생시킵니다. 이를 올바르게 처리하는 방법은 Files and exceptions 장에서 다룹니다.

input()은 프롬프트를 표준 출력에 쓰고, 표준 입력에서 한 줄을 읽으며, 후행 줄바꿈을 제거하고, 결과를 문자열로 반환합니다. 유형 추론은 없습니다. 터미널의 모든 것이 텍스트로 도착합니다; 경계에서 명시적으로 변환하여 필요한 유형을 선언합니다.

python
name = input("What's your name? ")
age = int(input("How old are you? "))

이 패턴(텍스트 수신, 필요한 유형으로 변환)은 외부 데이터가 도착하는 모든 곳에 적용됩니다. int(), float(), str()은 변환 도구입니다. 문자열을 변환할 수 없으면 Python은 Files and exceptions 장에서 다루는 ValueError를 발생시킵니다.

input()은 얇은 래퍼입니다: 프롬프트를 sys.stdout(표준 출력)에 쓰고, 플러시하여 프로그램이 차단되기 전에 프롬프트가 표시되도록 하고, sys.stdin(표준 입력)에서 한 줄을 읽으며, 후행 줄바꿈을 제거하고, str을 전달합니다. 설계상 항상 str입니다. 왜냐하면 Python이 "42"가 정수, float, 또는 리터럴 텍스트인지 추측할 수 없기 때문입니다. 그래서 경계에서 변환합니다. 이것이 Python I/O의 기본 형태입니다: 외부 데이터는 텍스트로 도착하고, 당신의 코드는 입력점에서 그 유형을 결정합니다.

python
name = input("Enter your name: ")
score = float(input("Enter your score (0.0 to 1.0): "))

print(f"Name:  {name!r}")      # !r은 보이지 않는 공백 드러냄
print(f"Score: {score:.1%}")
Juno사용자로부터 입력 받기input()은 프롬프트를 표시하고, 줄을 기다리고, 그들이 숫자를 입력했더라도 항상 string으로 전달합니다. 숫자가 필요할까요? int() 또는 float()으로 들어올 때 스스로 변환한 후 올바른 유형으로 계속 진행하세요.
Juno사용자로부터 입력 받기input()은 항상 str을 반환하고, 유형 추론 없음. `int()` 또는 `float()`로 경계에서 변환하고, 텍스트가 파싱되지 않으면 `ValueError`를 기대하세요. 그 수신-후-변환 패턴은 외부 데이터가 나타나는 모든 곳에서 보여집니다.
Juno사용자로부터 입력 받기 `input()`의 모든 것은 설계상 `str`이며, Python이 당신의 의도를 추측할 수 없기 때문입니다. 입력점에서 변환하고 파싱되지 않을 때 `ValueError`를 처리하세요. 외부 데이터가 내려오는 다른 모든 곳과 같은 형태입니다.

stderr에 쓰기

기본적으로 print()표준 출력에 쓰입니다: 터미널에 나타나고 파이프로 흐르는 스트림. Python은 또한 표준 에러를 가지고 있으며, 진단 및 경고를 위한 별도의 스트림입니다. 그들은 터미널에서 동일하게 보이지만 구별됩니다: 스크립트의 출력을 다른 명령으로 파이프할 때, stdout만 통과합니다. Stderr는 항상 터미널에 도달합니다.

stderr에 쓰기는 print()file 인자를 사용합니다. 이것은 Modules 장에서 다루는 sys를 임포트합니다. 지금은 두 스트림이 존재하고 왜 구별되는지를 알면 충분합니다.

실전

사용자 입력으로부터 자신을 개인화하는 퀴즈:

python
name = input("What's your name? ")
subject = input("Which subject? ")

print(f"Okay, {name}. Starting your {subject} quiz.")
print("Good luck!")

두 입력은 문자열로 돌아오고 f-string에 직접 들어갑니다. 그들을 텍스트가 아닌 숫자로 사용하고 있기 때문에 변환이 필요하지 않습니다.

정렬된 표 형태의 출력으로 온도 변환기:

python
celsius = float(input("Temperature in Celsius: "))
fahrenheit = celsius * 9 / 5 + 32

print(f"{'Celsius':>12} {'Fahrenheit':>12}")
print(f"{celsius:>12.1f} {fahrenheit:>12.1f}")

float()는 사용자로부터 정수 및 소수 모두를 처리합니다. :>12 지정자는 숫자가 몇 자리이든 열을 정렬된 상태로 유지합니다. 100-40을 입력해 보세요: 출력은 어느 쪽이든 깔끔하게 유지됩니다.

!r을 사용하여 Python이 받은 정확히 무엇을 표면화하여, 출력이 잘못되어 보일 때 유용합니다:

python
name = input("Enter your name: ")
score = float(input("Enter your score (0.0 to 1.0): "))

print(f"Name:   {name!r}")
print(f"Score:  {score!r}")
print()
print(f"Result: {name}: {score:.1%}")

{name}{name!r}은 입력이 깨끗할 때 동일하게 표시됩니다. 후행 공백 또는 다른 보이지 않는 문자가 있을 때 차이가 나타납니다. 디버깅하는 동안 !r 습관을 들이면 예상치 못한 값이 즉시 눈에 띕니다.