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

변수와 타입

docs.scrimba.com

모든 프로그램은 뭔가를 기억해야 합니다. 퀴즈는 플레이어의 이름을 기억해야 합니다. 게임은 현재 점수를 기억해야 합니다. 날씨 스크립트는 확인하는 도시를 기억해야 합니다. Python은 이를 위해 변수를 사용합니다. 프로그램 전체에서 사용할 수 있도록 값에 붙이는 이름입니다.

변수는 값을 가리키는 이름입니다. Python은 = 우측의 객체에 이름을 연결하고 언제든지 다시 연결할 수 있습니다. 타입은 이름이 아닌 값에 있습니다.

Python에서 변수는 **이름 바인딩**입니다: 객체(Python이 메모리에 보유하는 모든 값, 예: 문자열이나 숫자)를 가리키는 이름이지, 값을 담는 라벨이 붙은 상자가 아닙니다. 타입은 이름이 아닌 객체에 속하므로 한 이름이 한 줄에서는 str을 가리키다가 다음 줄에서는 int를 가리킬 수 있으며 오류가 발생하지 않습니다. 이러한 자유를 동적 타이핑이라고 합니다. 이름이 무엇을 가리킬 수 있는지를 제한하는 것이 없습니다.

python
player_name = "민지"
score = 0
city = "서울"

세 줄, 세 가지를 Python이 이제 기억합니다. 각각에 대해 Python은 우측의 값을 먼저 계산한 후 좌측의 이름 아래에 저장합니다. 나중에 해당 이름을 사용하면 Python이 값을 되돌려줍니다.

각 줄은 바인딩을 만듭니다. 좌측의 이름은 우측의 객체를 가리킵니다. Python은 우측을 먼저 계산한 다음 바인딩을 만듭니다.

각 할당은 현재 범위(해당 이름이 보이는 코드 영역, 보통 작업 중인 함수나 파일)에 이름을 바인딩합니다. Python은 항상 우측 전체를 먼저 계산한 후 아무것도 바인딩합니다. 정확히 이 이유 때문에 a, b = b, a는 한 줄에서 두 값을 교환합니다. 우측이 완전히 계산된 후 두 이름이 결과를 가리킵니다.

값 저장하기

= 기호는 수학 수업에서 온 거의 모든 사람을 헷갈리게 합니다. Python에서 =는 "같다"라는 뜻이 아닙니다. **이 값을 이 이름 아래에 저장하라**는 뜻입니다:

python
city = "서울"

city"서울"을 얻습니다. Python에게 말하는 것입니다: "서울"을 기억하고 city라고 표시하세요.

언제든지 변수의 값을 바꿀 수 있습니다. Python은 가장 최근의 값을 사용합니다:

python
score = 0
score = 10   # score는 이제 10
score = 15   # score는 이제 15

=할당입니다. 현재 범위에 이름을 객체에 바인딩합니다. 변수를 업데이트하는 표준 단축 표기는 **확장 할당**입니다:

python
score = 0
score += 10   # 같음: score = score + 10
score *= 2    # 같음: score = score * 2

한 번에 여러 이름을 바인딩할 수도 있습니다:

python
x, y, z = 1, 2, 3
a = b = 0        # 둘 다 0에서 시작

할당은 이름을 객체에 가리킵니다. 값을 새 컨테이너에 복사하지 않습니다. 따라서 두 이름은 정확히 같은 객체를 가리킬 수 있습니다:

python
a = "hello"
b = a
print(id(a) == id(b))   # True (두 이름 모두 한 객체를 가리킴)

b = "world"             # b가 새 객체로 재바인딩됨
print(id(a) == id(b))   # False
print(a)                # 여전히 "hello": b를 재바인딩해도 a에 영향 없음

id()는 객체의 식별성을 반환합니다. 그 객체가 존재하는 동안 그 객체에 유일한 숫자이므로 두 개의 같은 id는 "정확히 같은 객체"를 의미하며, 같은 값을 가진 두 개의 다른 객체가 아닙니다. 가리킴과 복사의 차이는 지금은 무시하기 쉽지만, 가변 객체(제자리에서 변경할 수 있는 것, 예: 리스트)에서 문제가 발생합니다. 한 리스트에 두 이름을 가리키게 하고 어느 이름으로든 변경하면 변경 사항이 둘 다에 나타납니다. 리스트와 딕셔너리는 이를 나중 장에서 구체적으로 보여줍니다.

타입 주석은 이름이 보유할 것으로 예상하는 타입을 기록합니다. 코드를 실행하지 않고 읽는 도구(타입 확인자와 에디터)를 위한 메모이며, Python은 프로그램 실행 중에 이를 무시합니다:

python
name: str = "민지"
score: int = 0
ratio: float = 0.85
Juno값 저장하기=는 수학 수업의 "같다"가 아니라 "이 값을 이 이름 아래에 숨겨라"입니다. 언제든지 변경하고 Python은 가장 최신의 값을 유지합니다. 선언도 설정도 없고, 이름을 지으면 존재합니다. 이 점을 과도하게 생각하지 않으려고 하는 데 정말 오래 걸렸습니다.
Juno값 저장하기=는 이름을 값에 가리킵니다. 언제든지 다시 가리킬 수 있습니다. 이름이 라벨이고 값이 물건입니다. 그게 전부입니다.
Juno값 저장하기=는 값을 상자에 넣는 게 아니라 이름을 객체에 묶습니다. 재할당은 이름만 옮기고, 이전 객체는 그대로 남습니다. 리스트가 나타나기 전에 기억하세요. 아니면 두 이름이 조용히 하나를 공유할 것입니다.

변수 이름 지정하기

이름을 선택합니다. Python은 몇 가지 엄격한 규칙을 가지고 있으며, 커뮤니티는 처음부터 채택할 가치가 있는 관례를 따릅니다. 명확한 이름은 몇 주 후에 코드를 읽을 수 있게 합니다. 암호화된 이름은 고통을 야기합니다.

Python은 작은 식별자 구문 규칙 집합을 시행합니다. 그 이상은 PEP 8 관례가 모든 Python 코드베이스와 도구에서 표준입니다.

Python이 식별자(이름의 기술적 단어)에 대해 실제로 시행하는 규칙은 최소한입니다. 나머지는 PEP 8, Python의 공식 스타일 가이드입니다. 인터프리터(코드를 실행하는 프로그램)는 이를 시행하지 않지만, 린터(스타일 문제와 가능한 버그를 표시하는 도구), 타입 확인자, 모든 전문 코드베이스는 이를 기대합니다. 이에 반대하는 것은 대부분 다음에 코드를 읽는 사람에게 마찰을 일으킵니다.

Python이 시행하는 규칙:

  • 문자, 숫자, 밑줄만 가능합니다. 공백이나 하이픈은 없습니다.
  • 문자나 밑줄로 시작해야 하며, 숫자로 시작할 수 없습니다
  • 대소문자 구분: score, Score, SCORE는 세 개의 다른 변수입니다

모두가 따르는 관례 (PEP 8):

스타일
변수와 함수snake_caseuser_name, total_price
상수UPPER_SNAKE_CASEMAX_RETRIES, BASE_URL
클래스PascalCaseUserAccount, DataLoader
python
# 명확한 이름, 한 눈에 읽을 수 있음
user_name = "민지"
total_price = 49.99
is_logged_in = True
MAX_RETRIES = 3

# 한 시간 안에 후회할 것들
x = "민지"
tp = 49.99
b = True

일찍 알아야 할 함정 하나: list, input, type, print 같은 Python 내장 함수 이름으로 변수를 이름 짓지 마세요. Python은 이를 허용하지만 그 범위의 나머지에서 내장 함수를 조용히 깨고 결과 오류는 추적하기 어렵습니다.

Python의 내장 함수를 가리우지 마세요. list, type, input, print, str에 할당하면 경고 없이 그 범위의 나머지에서 내장 함수를 덮어씁니다. 찾기 어려운 조용한 버그입니다.

UPPER_SNAKE_CASE는 관례이지 시행하는 것이 아닙니다. Python은 나중에 MAX_RETRIES = 99를 재할당하는 것을 막지 않을 것입니다. 그것은 다른 개발자에게 보내는 신호일 뿐입니다.

가리우기는 Python이 이미 제공하는 것과 일치하는 자신의 이름을 만드는 것을 의미합니다(예: list). Python이 이름을 찾을 때 자신의 로컬 이름을 내장 함수 전에 확인하므로 자신의 버전이 이기고 실제 list는 그 지점부터 숨겨집니다. 여전히 builtins.list로 접근할 수 있지만, 일반 코드는 더 이상 이를 보지 않습니다. 상수의 경우 UPPER_SNAKE_CASE는 시각적 신호일 뿐입니다. Python은 기꺼이 재할당을 허용합니다. 도구가 실제로 시행할 수 있는 상수를 원한다면 typing.Final로 주석을 달아 이름을 "재할당할 의도가 없음"으로 표시하면 타입 확인자가 재할당을 표시할 것입니다.

Juno변수 이름 지정하기 문자, 숫자, 밑줄, 문자나 밑줄로 시작합니다. snake_case를 따르면 됩니다. 초보자 실수 하나: 변수를 listprint라고 부르지 마세요. Python이 허용하면 나중에 모든 것이 이상해집니다. 경고도 없이요.
Juno변수 이름 지정하기snake_case 이름, UPPER_SNAKE_CASE 상수, 모든 도구가 이를 기대합니다. 그리고 listprint라고 이름 짓지 마세요. 조용히 내장 함수를 깨뜨릴 것입니다.
Juno변수 이름 지정하기 인터프리터는 거의 명명을 시행하지 않지만, 모든 린터는 시행합니다. snake_case에 반대하는 것은 고통을 초래할 뿐입니다. 실제 함정은 `list`처럼 내장 함수를 가리우는 것입니다. 조용히 깨지고, 이를 한 곳에서 멀리 떨어진 곳에서 합니다.

저장할 수 있는 것

Python은 거의 모든 프로그램에서 사용할 네 가지 타입을 가지고 있습니다. Python은 값을 어떻게 쓰는지에 따라 어느 타입을 의도했는지 파악합니다. 타입을 명시적으로 선언할 필요가 없습니다.

Python은 리터럴 구문에서 타입을 추론합니다. 이 네 가지 타입은 기본 값 공간을 다룹니다. 언어의 모든 것이 그 위에 구축됩니다.

Python의 모든 값은 전체 객체이며, 리터럴 조차도입니다(코드에 직접 쓰인 값, 예: 42 또는 "hi"). 객체라는 것은 값이 자신의 메서드(값에 부착된 함수)를 가지고 있다는 뜻이므로 "hi".upper()(3).bit_length()는 감싸거나 래핑할 필요 없이 리터럴에서 직접 작동합니다. 거의 생각할 필요가 없으며, 그것이 요점입니다. 아래의 네 가지 타입이 거의 모든 프로그램에서 사용하는 것입니다.

텍스트 (str)

모든 텍스트는 따옴표 안에 갑니다. 단일 또는 이중 따옴표입니다. 따옴표는 Python에게 리터럴 문자를 의도한다는 것을 알립니다. 변수 이름이 아닙니다. 문자열은 생성되면 제자리에서 변경될 수 없습니다. Strings 장은 문자열로 할 수 있는 모든 것을 다룹니다.

python
player_name = "민지"
city = "서울"
message = 'Game over'

텍스트에 아포스트로피가 포함되어 있으면 이중 따옴표를 사용하여 이스케이프할 필요가 없습니다:

python
note = "It's a great day"
note = 'It\'s a great day'   # 이스케이프를 사용하면 같은 결과

문자열은 단일 또는 이중 따옴표로 모든 텍스트를 담습니다. 그것들은 불변입니다: 문자열을 제자리에서 수정하는 작업은 없습니다. 모든 변환은 새로운 것을 반환합니다. 이것은 성능 문제가 됩니다. 루프 내에서 반복된 +는 매 단계마다 새 문자열 객체를 만듭니다. Strings 장은 효율적인 대안을 다룹니다.

python
player_name = "민지"
city = "서울"
note = "It's a great day"

str불변 Unicode 코드 포인트의 시퀀스입니다(불변은 생성 후 절대 변경될 수 없다는 뜻이며, 코드 포인트는 문자 자체이지 저장되는 원시 바이트가 아닙니다). 이 이유 때문에 len("café")는 5가 아니라 4입니다. 문자열은 변경될 수 없으므로 해시 가능하며 딕셔너리 키나 집합 멤버(절대 변경되지 않는 값)로 사용될 수 있습니다. 실제로 사용할 규칙 하나는 이것입니다. 문자열을 ==(같은 문자)로 비교하며, is(메모리의 같은 객체)로는 절대 비교하지 마세요. 두 개의 같은 문자열이 한 객체를 공유하는지 여부는 구현 세부사항이며 의존할 수 없습니다.

python
player_name = "민지"
city = "서울"
note = "It's a great day"
Juno텍스트 (str) 텍스트는 따옴표, 단일 또는 이중 따옴표, 선택하세요. 존재하면 제자리에서 변경할 수 없으며 괜찮습니다. 문자열을 편집하는 것처럼 보이는 모든 것은 실제로 새로운 문자열을 돌려줍니다.
Juno텍스트 (str) 문자열은 불변입니다. 제자리에서 편집하는 것은 없고, 항상 새 문자열을 돌려받습니다. 메서드 체이닝을 시작할 때 명심하세요.
Juno텍스트 (str) 불변 Unicode 실행이므로 `len("café")`는 4이고 문자열은 dict 키로 작동합니다. 실제로 사용할 부분: `==`로 비교하고, `is`로는 절대 하지 마세요.

정수 (int)

정수는 따옴표 없이 소수점 없이 입력합니다. Python은 이를 정수라고 부릅니다. 필요한 만큼 클 수 있습니다. Python은 특별한 노력 없이 임의로 큰 숫자를 처리합니다.

python
score = 0
age = 28
population = 8_100_000_000   # 밑줄은 가독성을 위해서만 사용됨

정수는 따옴표나 소수점 없이 작성됩니다. Python 정수는 임의의 정밀도입니다. 모든 값을 유지하도록 커집니다. C나 Java의 고정 크기 정수와 다릅니다. 숫자 리터럴의 밑줄은 미용이며 Python에서 무시합니다.

python
score = 0
age = 28
population = 8_100_000_000

두 가지를 유지할 가치가 있습니다. 첫째, Python의 int임의 정밀도입니다. RAM이 맞출 수 있는 모든 정수를 유지하도록 커집니다. 고정 크기 정수가 있는 언어에서 설계해야 하는 오버플로우(래핑 또는 오류)가 없습니다. 둘째, 숫자를 ==(같은 값)로 비교하고 is(같은 객체)로는 절대 비교하지 마세요. 두 개의 같은 정수가 같은 객체인지는 구현 세부사항입니다. CPython(표준 Python)은 작은 정수를 재사용하므로 id(1) == id(1)True이지만, 이는 더 큰 숫자에 대해 조용히 멈추므로 절대 이를 기반으로 구축하지 마세요.

python
score = 0
age = 28
population = 8_100_000_000
Juno정수 (int) 정수, 따옴표 없음, 소수점 없음. 최고의 부분, Python 정수는 원하는 만큼 커집니다. 오버플로우 없음. `8_100_000_000`의 밑줄은 읽을 수 있도록 하기 위함입니다.
Juno정수 (int) 정수는 임의 정밀도이므로 오버플로우를 걱정할 필요가 없습니다. 많은 자릿수가 있는 어떤 것에든 밑줄을 사용하세요.
Juno정수 (int) 정수는 RAM이 부족할 때까지 커집니다. 오버플로우는 비문제입니다. 유지할 가치 있는 한 가지 습관: 숫자를 `==`로 비교하고, `is`로는 아닙니다. 식별성은 캐싱 기이함이며 의존하지 마세요.

소수 (float)

소수점이 있는 숫자는 float입니다. 대부분의 계산에서 예상대로 작동합니다. 알아야 할 한 가지: 일부 소수 값은 이진법으로 정확히 저장할 수 없으므로 작은 반올림 오류가 생길 수 있습니다:

python
price = 4.99
temperature = 36.6

0.1 + 0.2   # 0.30000000000000004

일상 업무의 경우 이는 거의 중요하지 않습니다. 센트의 분수가 중요한 금융 계산의 경우 Python은 올바르게 처리하는 decimal 모듈을 가지고 있습니다. 이는 Numbers 장에서 다룹니다.

소수점이 있는 숫자는 float이 됩니다. Python float는 배정밀도입니다. 약 15~17 자릿수, 이진법으로 저장됩니다. 그 이진 저장이 잘 알려진 함정입니다. 0.1 + 0.20.30000000000000004이지 Python 버그가 아닙니다. 이진법이 소수를 표현하는 방식의 결과입니다. 돈이나 정확한 소수가 중요한 곳에서는 Python의 decimal 모듈에 도달하세요. 이는 Numbers 장에서 다룹니다.

python
price = 4.99
temperature = 36.6

float는 이진법(2진수)으로 저장되며, 대부분의 소수, 분모가 2의 거듭제곱이 아닌 것(예: 1/10)은 이진법으로 정확히 쓸 수 없습니다. 이것이 0.1 + 0.20.30000000000000004로 나오는 이유입니다. 프로덕션에서 중요한 규칙: 돈이나 정확한 동일성을 확인할 무엇이든 float를 사용하지 마세요. 정확한 10진 산술이 필요할 때 decimal.Decimal에 도달하거나 정확한 비율을 위해 fractions.Fraction에 도달하세요. 둘 다 Python 표준 라이브러리(Python과 함께 제공되는 도구)와 함께 옵니다. 이는 Modules 장에서 다룹니다.

python
price = 4.99
temperature = 36.6
Juno소수 (float) 소수점은 float를 만들고, 일상적인 것에는 괜찮습니다. 고전적인 함정 모두 한 번 치룰 것: `0.1 + 0.2`는 `0.30000000000000004`를 제공합니다. 버그가 아니라 이진법입니다. 돈을 위해 `decimal.Decimal`에 도달하세요.
Juno소수 (float) float는 이진법이므로 일부 소수는 정확할 수 없습니다. `0.1 + 0.2`는 `0.3`이 정확히 아닙니다. 대부분의 수학에는 좋으며, 돈에는 절대 아닙니다. 정확해야 할 때 `decimal.Decimal`을 사용하세요.
Juno소수 (float) float는 표류하며, 이것이 `0.1 + 0.2`가 깨진 것처럼 보이는 이유입니다. 규칙: 돈이나 정확한 동일성 확인을 위해 float는 없습니다. 정확한 10진법을 위해 `decimal.Decimal`, 비율을 위해 `fractions.Fraction`.

참 또는 거짓 (bool)

일부 것은 켜지거나 꺼집니다. Python은 이를 위해 부울을 사용합니다: 정확히 두 값, TrueFalse. 이 단계에서는 사소해 보이지만 프로그램의 모든 조건과 분기는 부울에서 실행됩니다.

python
is_logged_in = True
has_errors = False

Python은 조건에서 사용할 때 특정 값을 False인 것처럼 처리합니다: 0, 0.0, "", None(Python의 "여기에 값이 없음")은 모두 False처럼 동작합니다. 다른 모든 것은 True처럼 동작합니다. 이것은 Control flow 장에서 유용하게 됩니다.

bool은 정확히 True 또는 False를 담습니다. 비교로 반환되고 조건으로 소비됩니다. Python은 더 넓은 진실거짓 값 집합을 가집니다. 0 값, 빈 컨테이너, None은 거짓입니다. 다른 모든 것은 진실입니다. 유용한 세부사항 하나: boolint의 서브클래스이므로 True + True2로 계산됩니다.

python
is_logged_in = True
has_errors = False

boolint 위에 구축되어 있습니다(서브클래스, 즉 int의 특수한 종류). TrueFalse는 유일한 두 bool 객체이며 1과 0의 가치가 있습니다. 조건에서 거짓 값(거짓으로 계산되는 것)은: 0(0, 0.0), 빈 컨테이너("", [], (), {}), None, False 자체입니다. 다른 모든 것은 진실입니다. 자신의 클래스는 __bool__ 또는 __len__(더블 밑줄이 있는 특수 "던더" 메서드, Python이 예/아니오 답변이 필요할 때 부르는)를 정의하여 진실을 결정할 수 있습니다. 그리고 boolint이므로 isinstance(True, int)True이며, 이는 타입을 확인하는 코드에서 걸릴 수 있습니다.

python
is_logged_in = True
has_errors = False
Juno참 또는 거짓 (bool) 두 값, `True`와 `False`, 그리고 쓸 모든 `if` 뒤에 있습니다. 재미있는 부분: `0`, `""`, `[]` 그리고 `None` 모두 `False`로 계산하고, 다른 모든 것은 `True`로 계산합니다.
Juno참 또는 거짓 (bool) `bool`은 비교에서 `True`/`False`입니다. Python은 또한 진실과 거짓을 가집니다: 빈 것, 0과 `None`은 거짓입니다. 이것이 `if my_list:`가 그렇게 좋게 읽히는 이유입니다.
Juno참 또는 거짓 (bool) `bool`은 비밀스럽게 `int`이므로 `isinstance(True, int)`는 `True`이며, 이는 한 날 타입 확인에서 놀랠 것입니다. 거짓은 0, 비음 그리고 `None`입니다. 사용자 정의 객체는 `__bool__` 또는 `__len__`로 자신의 진실을 선택합니다.

타입 확인 및 변환

값의 타입이 확실하지 않을 때 type()이 알려줍니다. 값이 특정 타입인지 확인하려면 isinstance()가 더 신뢰할 수 있는 도구입니다:

python
print(type("hello"))   # <class 'str'>
print(type(42))        # <class 'int'>
print(type(3.14))      # <class 'float'>
print(type(True))      # <class 'bool'>

isinstance(42, int)    # True
isinstance("hi", str)  # True

type()은 객체의 정확한 타입을 반환합니다. 자신의 코드에서 타입 확인을 위해 isinstance()가 선호됩니다. 상속을 처리하며 type() 비교는 처리하지 않습니다.

python
print(type(42))          # <class 'int'>
isinstance(True, int)    # True   (bool은 int의 서브클래스)
type(True) == int        # False  (정확한 일치만, 서브클래스 아님)

type(x)x의 정확한 타입을 제공합니다. isinstance(x, T)는 더 많이 합니다. MRO(메서드 해석 순서, Python이 상속 체인을 따라 검색하는 정렬된 클래스 목록, 클래스가 구축되는 부모 타입의 행)를 따릅니다. 그래서 부모 타입에도 True를 반환합니다. 이것이 isinstance(True, int)True인 반면 type(True) == intFalse인 이유입니다(정확한 일치 확인). 실제 코드에서 값이 사용하기 전에 예상하는 타입인지 확인하는 타입 가드isinstance()에 도달하세요.

python
isinstance(True, int)    # True
type(True) == int        # False

Python은 타입을 자동으로 혼합하지 않습니다. 문자열과 숫자를 연결하면 TypeError가 발생합니다:

python
score = 42
print("Your score is " + score)        # TypeError
print("Your score is " + str(score))   # 작동함

타입 이름을 함수로 사용하여 명시적으로 변환하세요:

호출결과
str(42)"42"
int(3.9)3 (자르기, 반올림 아님)
float("3.14")3.14
int("3.14")ValueError: 10진 문자열을 정수로 직접 변환할 수 없습니다
int(float("3.14"))3 (먼저 float로 변환한 후 int로)
bool(0) / bool("")False
Juno타입 확인 및 변환 `type()`은 무엇이 무엇인지 말해 줍니다. `isinstance()`는 주어진 타입인지 확인합니다. 그리고 Python은 문자열과 숫자를 접착하지 않으므로 `str()` 또는 `int()`로 먼저 변환하세요. 모두 한 번 이것을 치룬다.
Juno타입 확인 및 변환 `type() ==` 위에 `isinstance()`에 도달하세요. 상속을 존경합니다. 변환은 항상 명시적이므로 문자열과 숫자를 연결하기 전에 변환하세요.
Juno타입 확인 및 변환 `isinstance()`는 타입 가드이며, 클래스 트리를 따르며 `type(x) == T`는 정확히만 일치합니다. 변환은 의도적으로 명시적입니다. `int("3.14")`는 추측하기보다 발생하는 것을 선호하므로 먼저 `float`을 통해 가세요.

실제로

네 가지 타입 모두 작은 스크립트에서 함께 작동합니다. 출력 줄은 f-문자열을 사용하여 텍스트에 값을 포함합니다. 여는 따옴표 전에 f를 넣고 모든 변수를 {}로 감싸세요. Python은 변수의 실제 값으로 대체합니다. 다음 장에서 올바르게 배웁니다.

python
player_name = "민지"
level = 3
accuracy = 0.94
is_premium = True

print(f"{player_name}{accuracy:.0%} 정확도로 {level}단계에 있습니다.")
print(f"프리미엄 계정: {is_premium}")

타입은 중요합니다. level + 1은 작동하지만 player_name + 1은 작동하지 않습니다. 각 변수는 정확히 한 종류의 것을 담습니다. Python은 자동으로 혼합하지 않습니다.

모든 네 가지 타입이 있는 현실적인 구성 블록입니다. 상수는 런타임 상태와 분리되어 있습니다. f"..." 구문은 f-문자열입니다. {} 내의 모든 표현은 런타임에서 계산되고 출력에 포함됩니다. Output and input 장에서 완전히 다룹니다.

python
BASE_URL = "https://api.example.com"
MAX_RETRIES = 3
DEBUG = False

user_name = "민지"
request_count = 0
last_response = None

request_count += 1
print(f"[{request_count}] {BASE_URL} | debug={DEBUG}")

None은 "아직 값이 없음"을 위한 표준 자리 표시자입니다. 그것의 타입은 NoneType이고 조건에서 거짓으로 작동합니다. 프로그램 나중에 의미가 있을 때까지 변수의 기본값으로 사용하세요.

같은 구성, 이제 인라인 타입 주석이 있습니다. 주석은 이름이 보유할 것으로 예상하는 타입을 기록합니다. 이는 타입 확인자와 에디터(IDE)를 위해 존재하며, Python은 프로그램 실행 중에 이를 무시합니다:

python
BASE_URL: str = "https://api.example.com"
MAX_RETRIES: int = 3
DEBUG: bool = False

user_name: str = "민지"
request_count: int = 0
last_response: str | None = None

str | None합집합 타입이며, Python 3.10에 추가되었습니다. 값이 문자열 또는 None 중 하나라고 말합니다. 더 이전 버전에서 같은 것을 내장 typing 모듈에서 가져온 Optional[str]로 작성합니다. str | None 형식은 최소 버전이 허용할 때마다 현대 Python에서 선호하는 것입니다.