Python & AI Tutorials Logo
Python 프로그래밍

3. 변수와 기본 데이터 타입

2장에서 텍스트를 출력하고, 입력을 받고, 기본 연산을 수행하는 간단한 프로그램을 작성하는 방법을 배웠습니다. 하지만 그 프로그램들에는 큰 한계가 있었습니다. 나중에 사용할 정보를 저장할 수 없었고, 서로 다른 종류의 데이터를 복잡한 방식으로 다룰 수도 없었습니다. 이 장에서는 Python이 변수 (variable)데이터 타입 (data type) 을 사용해 정보를 저장하고 관리하는 방법을 배웁니다.

변수는 정보를 담고 있는 라벨이 붙은 컨테이너라고 생각할 수 있습니다. 집에서 물건을 정리할 때 라벨이 붙은 상자를 사용하는 것처럼, Python은 프로그램 안의 데이터를 정리하고 관리하기 위해 변수를 사용합니다. 하지만 모든 데이터가 같은 것은 아닙니다. 숫자는 텍스트와 근본적으로 다르며, Python은 자신이 어떤 종류의 데이터를 다루는지 알아야 합니다. 여기서 데이터 타입 이 필요합니다.

이 장을 마치면 다음을 이해하게 됩니다:

  • 변수를 올바르게 만들고 이름 짓는 방법
  • 데이터 타입이 무엇이고 왜 중요한지
  • 숫자, 텍스트, 논리 값을 다루는 방법
  • 서로 다른 데이터 타입 사이를 변환하는 방법
  • Python이 내부적으로 데이터를 표현하는 방식

이 개념들은 Python에서 앞으로 하게 될 모든 것의 기초가 되므로, 다양한 실용 예제와 함께 자세히 살펴보겠습니다.

3.1) 변수 이름 짓기와 생성하기

3.1.1) 변수란 무엇이며 왜 중요한가

변수 (variable) 는 컴퓨터 메모리에 저장된 값을 가리키는 이름입니다. 변수를 만들면, 어떤 데이터 조각을 가리키는 라벨을 만드는 것과 같습니다. 이를 통해 다음과 같은 일을 할 수 있습니다:

  1. 프로그램에서 나중에 사용할 정보를 저장할 수 있습니다.
  2. 같은 값을 여러 번 사용할 때, 매번 다시 입력하지 않고 반복해서 참조할 수 있습니다.
  3. 프로그램이 실행되는 동안 값을 갱신할 수 있습니다.
  4. 의미 없는 값 대신 의미 있는 이름을 사용해 코드를 읽기 쉽게 만들 수 있습니다.

구체적인 예를 보겠습니다. 변수를 사용하지 않고 직사각형의 넓이를 계산하려면 다음과 같이 쓸 수 있습니다:

python
# without_variables.py
print("Rectangle area:", 15 * 8)

이 코드는 동작하지만, 이 가로와 세로 길이를 여러 번 사용해야 한다면 어떻게 될까요? 그리고 15와 8이 무엇을 의미하는지도 알기 어렵습니다. 변수를 사용하면 코드가 더 명확하고 유연해집니다:

python
# with_variables.py
length = 15
width = 8
area = length * width
print("Rectangle area:", area)  # Output: Rectangle area: 120

이제 코드는 스스로 설명이 됩니다. 이 코드를 읽는 사람은, 우리가 특정한 가로와 세로 길이를 가진 직사각형의 넓이를 계산하고 있다는 것을 바로 이해할 수 있습니다. 만약 길이를 바꿔야 한다면, 위쪽의 변수 할당만 수정하면 됩니다.

3.1.2) 할당으로 변수 만들기

Python에서는 할당 연산자 (assignment operator) (=)를 사용해 변수를 만듭니다. 기본 구문은 다음과 같습니다:

python
variable_name = value

= 기호는 수학에서 말하는 "같다"를 의미하지 않습니다. 대신 "왼쪽에 있는 이름에 오른쪽의 값을 할당한다"는 뜻입니다. 이는 매우 중요한 차이입니다. Python이 이 문장을 보면 다음과 같이 처리합니다:

  1. = 오른쪽에 있는 표현식을 평가합니다.
  2. 왼쪽에 있는 변수 이름을 생성하거나 갱신합니다.
  3. 그 이름이 평가 결과 값을 가리키게 합니다.

변수를 만드는 몇 가지 예시는 다음과 같습니다:

python
# creating_variables.py
age = 25
temperature = 72.5
name = "Alice"
is_student = True
 
print(age)          # Output: 25
print(temperature)  # Output: 72.5
print(name)         # Output: Alice
print(is_student)   # Output: True

각 변수가 어떤 타입의 데이터를 담게 될지 미리 선언할 필요가 없다는 점에 주목하세요. Python은 여러분이 할당한 값에 따라 자동으로 타입을 결정합니다. 이를 동적 타이핑 (dynamic typing) 이라고 하며, Python을 매우 유연하고 사용하기 쉽게 만들어 줍니다.

또한 다중 할당 (multiple assignment) 을 사용해 한 줄에 여러 변수를 만들 수도 있습니다:

python
# multiple_assignment.py
x, y, z = 10, 20, 30
print(x)  # Output: 10
print(y)  # Output: 20
print(z)  # Output: 30
 
# You can even assign the same value to multiple variables
a = b = c = 100
print(a, b, c)  # Output: 100 100 100

첫 번째 형태(튜플 언패킹 (tuple unpacking) 이라고 부르며, 튜플은 14장에서 배웁니다)는 각 값을 순서대로 대응되는 변수에 할당합니다. 두 번째 형태는 같은 값을 세 변수 모두에 할당합니다.

3.1.3) 변수 이름 규칙과 관례

Python에는 유효한 변수 이름을 위한 구체적인 규칙이 있습니다. 이 중 일부는 반드시 지켜야 하는 요건이고, 나머지는 다른 Python 코드와 일관성을 유지하고 가독성을 높이기 위한 관례입니다.

요건(반드시 지켜야 함):

  1. 문자(a-z, A-Z) 또는 밑줄(_)로 시작해야 합니다. 변수 이름은 숫자로 시작할 수 없습니다.
  2. 문자, 숫자, 밑줄을 포함할 수 있습니다. 첫 글자 이후에는 문자, 숫자, 밑줄을 어떤 조합으로든 사용할 수 있습니다.
  3. 공백이나 특수 문자를 포함할 수 없습니다. 공백, 하이픈, 대부분의 구두점은 허용되지 않습니다.
  4. Python 키워드일 수 없습니다. if, for, while, def 등은 Python이 자체적으로 사용하는 예약어입니다.
  5. 대소문자를 구분합니다. age, Age, AGE는 서로 다른 세 변수입니다.

유효한 변수 이름과 유효하지 않은 변수 이름의 예는 다음과 같습니다:

python
# valid_names.py
# Valid variable names
user_age = 30
firstName = "John"
total_2024 = 1000
_private = "hidden"
x = 5
MAX_SIZE = 100
 
# Invalid variable names (these will cause errors)
# 2nd_place = "silver"      # Error: starts with digit
# user-name = "alice"       # Error: contains hyphen
# total amount = 500        # Error: contains space
# class = "Python 101"      # Error: 'class' is a keyword

관례(가독성을 위해 지키는 것이 좋음):

  1. 일반 변수에는 소문자와 밑줄을 사용합니다. 이런 스타일을 snake_case라고 하며 Python의 표준입니다.

    python
    user_age = 25
    total_price = 99.99
    is_valid = True
  2. 상수에는 모두 대문자를 사용합니다. 프로그램 실행 중 바뀌지 않아야 하는 값입니다.

    python
    MAX_ATTEMPTS = 3
    PI = 3.14159
    DEFAULT_COLOR = "blue"
  3. 설명적인 이름을 사용합니다. 변수 이름만 보고도 무엇을 나타내는지 알 수 있어야 합니다.

    python
    # Good: clear and descriptive
    student_count = 30
    average_temperature = 72.5
     
    # Poor: unclear abbreviations
    sc = 30
    avg_tmp = 72.5
     
    # Poor: too generic
    x = 30
    data = 72.5
  4. 특정한 경우를 제외하고 한 글자짜리 이름은 피합니다. i, j, k 같은 이름은 반복문 (loop)에서 카운터로 사용하는 경우(11장에서 배웁니다)에 괜찮고, x, y, z는 좌표를 나타낼 때 괜찮습니다. 그 외에는 의미 있는 이름을 사용하는 것이 좋습니다.

  5. 내장 함수 이름과 같은 이름은 피합니다. Python은 허용하지만, list, str, int, print 같은 이름은 내장 함수 이름이므로 사용하지 않는 것이 좋습니다.

좋은 이름 짓기 관례를 보여 주는 실용적인 예를 보겠습니다:

python
# good_naming.py
# Constants at the top
SALES_TAX_RATE = 0.08
DISCOUNT_THRESHOLD = 100
 
# Descriptive variable names
item_price = 75.00
quantity = 3
subtotal = item_price * quantity
 
# Clear boolean variable
qualifies_for_discount = subtotal >= DISCOUNT_THRESHOLD
 
if qualifies_for_discount:
    discount = subtotal * 0.10
    subtotal = subtotal - discount
    print("Discount applied: $", discount)
 
tax = subtotal * SALES_TAX_RATE
total = subtotal + tax
 
print("Subtotal: $", subtotal)
print("Tax: $", tax)
print("Total: $", total)
# Output:
# Subtotal: $ 202.5
# Tax: $ 16.2
# Total: $ 218.7

변수 이름만으로도 코드가 스스로 설명이 된다는 점에 주목하세요. 주석이 없어도 프로그램이 무엇을 계산하는지 이해할 수 있습니다.

3.1.4) 식에서 변수 사용하기

변수를 만들고 나면, 그 변수가 나타내는 값을 사용할 수 있는 어디에서든 사용할 수 있습니다. Python은 표현식을 평가할 때 자동으로 변수의 현재 값을 대입합니다:

python
# using_variables.py
# Create some variables
hours_worked = 40
hourly_rate = 25.50
 
# Use variables in calculations
gross_pay = hours_worked * hourly_rate
print("Gross pay:", gross_pay)  # Output: Gross pay: 1020.0
 
# Use variables in other expressions
bonus = gross_pay * 0.10
total_pay = gross_pay + bonus
print("Total with bonus:", total_pay)  # Output: Total with bonus: 1122.0
 
# Use variables in strings (we'll learn more about this in Chapter 5)
message = "You worked " + str(hours_worked) + " hours"
print(message)  # Output: You worked 40 hours

변수는 2장에서 배운 함수들과 함께 사용할 수도 있습니다:

python
# variables_with_functions.py
name = input("What is your name? ")
age = input("What is your age? ")
 
greeting = "Hello, " + name + "!"
print(greeting)
 
age_next_year = int(age) + 1
print("Next year you will be", age_next_year, "years old.")
# If user enters "Alice" and "25":
# Output: Hello, Alice!
# Output: Next year you will be 26 years old.

이 예시는 중요한 개념도 보여 줍니다. input() 함수는 항상 텍스트(문자열 (string))을 반환하므로, 수학 연산을 하고 싶다면 먼저 숫자로 변환해야 합니다. 이 변환 과정은 이 장의 뒷부분(3.7절)에서 자세히 살펴보겠습니다.

3.2) 변수의 할당과 재할당

3.2.1) 할당 이해하기

값을 변수에 할당하면, Python은 변수 이름과 메모리에 있는 값 사이에 연결을 만듭니다. 변수는 물리적인 의미에서 값을 "포함"하는 것이 아니라, 메모리에 저장된 값을 참조 (refer) 하거나 가리키는 (point to) 이름이라는 점을 이해하는 것이 중요합니다.

이것은 값이 들어 있는 상자에 이름이 적힌 포스트잇을 붙여 놓는 것과 같습니다. 변수(포스트잇)는 값 자체가 아니라, 값이 들어 있는 상자를 가리킵니다. 변수를 재할당할 때는, 포스트잇을 다른 상자로 옮기는 것이지, 원래 상자 안의 내용을 바꾸는 것이 아닙니다.

이 차이는 재할당을 이야기할 때 중요해집니다. 변수를 할당하고 재할당할 때 무슨 일이 일어나는지 살펴보겠습니다:

python
# assignment_basics.py
x = 10
print(x)  # Output: 10
 
# Reassign x to a new value
x = 20
print(x)  # Output: 20
 
# The old value (10) is gone; x now refers to 20

여기에서 단계별로 어떤 일이 일어났는지 보겠습니다:

  1. x = 10: Python은 메모리에 정수 값 10을 만들고, x라는 이름이 그것을 가리키게 합니다.
  2. print(x): Python은 x가 가리키는 값(10)을 찾아 출력합니다.
  3. x = 20: Python은 메모리에 정수 값 20을 만들고, x가 이 새로운 값을 가리키게 합니다.
  4. print(x): Python은 이제 x가 가리키는 값(20)을 찾아 출력합니다.

원래 값 10은 잠시 동안 메모리에 남아 있지만, 더 이상 어떤 변수도 그것을 가리키지 않으므로, Python의 자동 메모리 관리 기능인 가비지 컬렉션 (garbage collection) 이 결국 정리해 줍니다.

3.2.2) 재할당과 변수 갱신

프로그래밍에서 가장 흔한 패턴 중 하나는 변수의 현재 값을 바탕으로 그 변수를 갱신하는 것입니다. 예를 들어, 카운터를 증가시키거나, 누적 합계를 늘리거나, 어떤 계산을 통해 값을 수정할 수 있습니다:

python
# updating_variables.py
score = 0
print("Initial score:", score)  # Output: Initial score: 0
 
# Add 10 points
score = score + 10
print("After first update:", score)  # Output: After first update: 10
 
# Add 5 more points
score = score + 5
print("After second update:", score)  # Output: After second update: 15
 
# Double the score
score = score * 2
print("After doubling:", score)  # Output: After doubling: 30

score = score + 10에서 일어나는 일을 살펴보겠습니다:

  1. Python은 오른쪽 score + 10을 평가합니다.
  2. 현재 score의 값(0)을 조회합니다.
  3. 0 + 10을 계산해서 10을 얻습니다.
  4. 이 새 값(10)을 score에 할당합니다.
  5. 이제 score는 0이 아니라 10을 가리킵니다.

이 패턴은 너무 자주 등장하기 때문에 Python은 이를 위한 축약 연산자를 제공합니다(4장 4.3절에서 배웁니다). 하지만 지금은 이 전체 형태를 이해하는 것이 중요합니다. 이 형태는 연산 순서를 분명하게 보여 줍니다. 즉, 오른쪽을 완전히 계산한 다음, 왼쪽에 할당합니다.

3.2.3) 변수는 서로 독립적이다

한 변수를 다른 변수에 할당하면, Python은 값 자체를 복사하는 대신 참조를 복사합니다(숫자와 문자열 같은 단순 타입에서는 이 동작이 직관적입니다). 하지만 이 장에서 배우는 기본 타입의 경우, 변수들은 할당 이후 서로 독립적으로 동작합니다:

python
# independent_variables.py
a = 10
b = a  # b now refers to the same value as a (10)
print("a:", a)  # Output: a: 10
print("b:", b)  # Output: b: 10
 
# Change a
a = 20
print("After changing a:")
print("a:", a)  # Output: a: 20
print("b:", b)  # Output: b: 10 (unchanged!)

b = a를 했을 때, b는 그 순간 a가 가리키고 있던 값(10)을 가리키게 됩니다. 나중에 a가 20을 가리키도록 바꾸더라도, b는 영향을 받지 않습니다. 여전히 10을 가리킵니다.

이 동작은 숫자와 문자열에서는 단순하지만, 리스트(list)와 딕셔너리(dictionary) 같은 컬렉션 타입에서는 더 복잡해집니다. Python의 객체 모델과 참조 의미론을 다루는 17장에서 이 부분을 자세히 살펴보겠습니다.

3.2.4) 할당 전에 변수를 사용하기

초보자들이 흔히 하는 실수 중 하나는, 값을 할당하기 전에 변수를 사용하려는 것입니다. 이렇게 하면 Python은 NameError를 발생시킵니다:

python
# undefined_variable.py
print(total)  # Error: NameError: name 'total' is not defined

이 오류는 Python이 total이 무엇을 가리키는지 알지 못하기 때문에 발생합니다. 아직 만들지 않았기 때문입니다. 해결 방법은 간단합니다. 사용하기 전에 먼저 변수에 값을 할당하면 됩니다:

python
# defined_variable.py
total = 0  # Initialize the variable first
print(total)  # Output: 0
 
# Now we can update it
total = total + 10
print(total)  # Output: 10

이처럼 변수를 초기 값으로 초기화 (initialize) 한 뒤 사용하는 패턴은 프로그래밍에서 기본입니다. 특히 반복문 (loop)에서 카운터나 누적 합계를 다룰 때(10장에서 다룹니다) 자주 보게 될 것입니다.

3.2.5) 변수 값 교환하기

두 변수의 값을 서로 바꾸는(스와핑) 작업은 자주 등장합니다. 많은 프로그래밍 언어에서는 이를 위해 임시 변수가 필요합니다:

python
# swap_with_temp.py
x = 10
y = 20
print("Before swap: x =", x, ", y =", y)  # Output: Before swap: x = 10 , y = 20
 
# Swap using a temporary variable
temp = x    # Save x's value
x = y       # Put y's value in x
y = temp    # Put saved value in y
 
print("After swap: x =", x, ", y =", y)  # Output: After swap: x = 20 , y = 10

하지만 Python은 동시 할당 (simultaneous assignment) 을 사용해 더 우아한 방법을 제공합니다:

python
# swap_pythonic.py
x = 10
y = 20
print("Before swap: x =", x, ", y =", y)  # Output: Before swap: x = 10 , y = 20
 
# Swap in one line
x, y = y, x
 
print("After swap: x =", x, ", y =", y)  # Output: After swap: x = 20 , y = 10

이 코드는 Python이 오른쪽(y, x) 전체를 어떤 할당도 하기 전에 먼저 평가하기 때문에 동작합니다. Python은 먼저 yx의 값을 담은 임시 구조를 만들고, 그 값을 각각 xy에 언패킹해서 넣습니다. 이는 흔한 작업을 간단하고 읽기 쉽게 만드는 Python 철학의 좋은 예입니다.

3.3) 데이터 타입과 type()의 개념

3.3.1) 데이터 타입이란?

데이터 타입 (data type) 또는 간단히 타입 (type) 은 값이 어떤 종류의 데이터인지를 정의하고, 그 값에 대해 어떤 연산을 수행할 수 있는지 정해 줍니다. 데이터 타입은 Python에게 서로 다른 종류의 정보를 어떻게 해석하고 다뤄야 하는지 알려 주는 범주라고 생각하면 됩니다.

예를 들어:

  • 숫자 42정수 (integer) 입니다(소수점이 없는 전체 수).
  • 숫자 3.14부동소수점 수 (floating-point number) 입니다(소수점이 있는 수).
  • 텍스트 "Hello"문자열 (string) 입니다(문자들의 시퀀스).
  • True불리언 (boolean) 입니다(논리적인 참/거짓 값).

데이터 타입이 왜 중요할까요? 서로 다른 타입은 서로 다른 연산을 지원하기 때문입니다:

python
# type_operations.py
# You can add numbers
result1 = 10 + 5
print(result1)  # Output: 15
 
# You can also "add" strings (concatenation)
result2 = "Hello" + " " + "World"
print(result2)  # Output: Hello World
 
# But you can't add a number and a string directly
# result3 = 10 + "5"  # Error: TypeError: unsupported operand type(s)

마지막 예시에서 오류가 발생하는 이유는, 숫자와 문자열을 어떻게 더해야 할지 Python이 알지 못하기 때문입니다. 숫자를 텍스트로 바꿔서 이어 붙여야 할까요? 아니면 텍스트를 숫자로 바꿔서 수학적으로 더해야 할까요? Python은 한쪽 타입에 맞게 명시적으로 변환해 줄 것을 요구합니다(방법은 3.7절에서 배웁니다).

3.3.2) type()으로 데이터 타입 확인하기

Python에는 값이나 변수의 타입을 알려주는 내장 함수 type()이 있습니다. 데이터의 타입을 이해하고 디버깅하는 데 매우 유용합니다:

python
# checking_types.py
# Check types of literal values
print(type(42))        # Output: <class 'int'>
print(type(3.14))      # Output: <class 'float'>
print(type("Hello"))   # Output: <class 'str'>
print(type(True))      # Output: <class 'bool'>
 
# Check types of variables
age = 25
name = "Alice"
temperature = 98.6
is_valid = False
 
print(type(age))         # Output: <class 'int'>
print(type(name))        # Output: <class 'str'>
print(type(temperature)) # Output: <class 'float'>
print(type(is_valid))    # Output: <class 'bool'>

<class 'int'>라는 출력은 "이 값은 int라는 클래스(타입)에 속한다"는 뜻입니다. Python에서는 타입이 사실 클래스이기도 합니다(클래스는 책의 VIII부에서 자세히 다루지만, 지금은 이 둘을 같은 의미로 생각해도 괜찮습니다).

3.3.3) Python의 동적 타이핑

Python은 동적 타이핑 (dynamic typing) 언어입니다. 이는 다음을 의미합니다:

  1. 변수는 고정된 타입을 갖지 않습니다. 하나의 변수가 시점에 따라 서로 다른 타입의 값을 가리킬 수 있습니다.
  2. 타입은 실행 시간에 결정됩니다. 코드를 작성할 때가 아니라 프로그램이 실행될 때 Python이 타입을 결정합니다.
  3. 타입을 명시적으로 선언할 필요가 없습니다. 다른 언어와 달리 "이 변수는 정수만 가진다"라고 미리 선언하지 않아도 됩니다.

동적 타이핑이 어떻게 동작하는지 예를 보겠습니다:

python
# dynamic_typing.py
x = 42
print(x, "is of type", type(x))  # Output: 42 is of type <class 'int'>
 
x = "Hello"
print(x, "is of type", type(x))  # Output: Hello is of type <class 'str'>
 
x = 3.14
print(x, "is of type", type(x))  # Output: 3.14 is of type <class 'float'>

x가 프로그램의 서로 다른 지점에서 서로 다른 타입의 값을 가리킬 수 있다는 점을 보세요. Python은 불평하지 않고, x가 현재 가리키는 타입을 바꿀 뿐입니다.

이러한 유연성은 편리하지만, 주의해야 할 점도 있습니다. 어떤 변수가 숫자를 담고 있을 거라 기대했는데 실제로는 문자열을 담고 있다면, 예상치 못한 오류가 발생할 수 있습니다:

python
# type_confusion.py
value = "100"  # This is a string, not a number!
 
# Trying to do math with it will fail
# result = value + 50  # Error: TypeError: can only concatenate str to str
 
# You need to convert it first
result = int(value) + 50
print(result)  # Output: 150

이 때문에 데이터 타입을 이해하는 것이 매우 중요합니다. 어떤 연산이 성공하고, 어떤 연산이 오류를 낼지 예측할 수 있게 해 줍니다.

3.3.4) Python 내장 타입 개요

Python에는 여러 내장 데이터 타입이 있습니다. 이 장에서는 그 중 가장 기본적인 것들에 집중합니다:

Python Built-in Types

Numeric Types

Text Type

Boolean Type

None Type

Collection Types

int: Integers

float: Decimal Numbers

complex: Complex Numbers

str: Text/Strings

bool: True/False

NoneType: None

list, tuple, dict, set...

이 장에서 다룰 타입은 다음과 같습니다:

  • int: 정수(전체 수)
  • float: 부동소수점 수(소수점 있는 수)
  • str: 문자열(텍스트)
  • bool: 불리언 값(TrueFalse)
  • NoneType: 특수 값 None

또한 허수 부분을 가지는 복소수 (complex) 타입을 간단히 언급하겠지만, 일상적인 프로그래밍에서는 거의 필요하지 않습니다. 리스트(list), 튜플(tuple), 딕셔너리(dictionary), 세트(set) 같은 컬렉션 타입 (collection types) 은 매우 중요하기 때문에, 책의 IV부에서 이들을 위한 별도의 장을 마련했습니다.

3.3.5) 실전에서의 타입 확인

사용자 입력이나 외부 데이터와 작업할 때는 타입을 이해하는 것이 특히 중요해집니다. input()은 사용자가 숫자를 입력하더라도 항상 문자열을 반환한다는 점을 기억하세요:

python
# input_types.py
user_input = input("Enter a number: ")
print("You entered:", user_input)
print("Type:", type(user_input))  # Output: Type: <class 'str'>
 
# Even if user types "42", it's still a string!
# To use it as a number, convert it:
number = int(user_input)
print("As a number:", number)
print("Type:", type(number))  # Output: Type: <class 'int'>
 
# Now we can do math with it
doubled = number * 2
print("Doubled:", doubled)

이 프로그램을 실행해서 42를 입력하면 다음과 같은 결과를 볼 수 있습니다:

Enter a number: 42
You entered: 42
Type: <class 'str'>
As a number: 42
Type: <class 'int'>
Doubled: 84

이 예시는 중요한 점을 보여 줍니다. "42"라는 문자열과 정수 42는 Python에서 서로 다른 것입니다. 출력했을 때는 비슷해 보이지만, 문자열은 문자 '4''2' 두 개로 이루어진 시퀀스이고, 정수는 수학 연산에 사용할 수 있는 수치 값입니다.

3.4) 정수와 부동소수점 수

3.4.1) 정수 (int)

정수 (integer) 타입 int는 소수점이 없는 전체 수입니다. 정수는 양수, 음수, 0 모두 가능하며, Python 3에서는 정수의 크기가 사실상 무제한입니다. 컴퓨터의 사용 가능한 메모리에 의해서만 제한됩니다.

python
# integers.py
# Positive integers
age = 25
year = 2024
population = 8000000000
 
# Negative integers
temperature = -15
debt = -5000
 
# Zero
balance = 0
 
# Very large integers (Python handles these easily)
huge_number = 123456789012345678901234567890
print(huge_number)  # Output: 123456789012345678901234567890
print(type(huge_number))  # Output: <class 'int'>

Python은 큰 숫자를 읽기 쉽게 하기 위해 밑줄을 사용할 수 있게 해 줍니다. 밑줄은 Python이 무시하지만, 사람에게는 숫자를 읽기 쉽게 만들어 줍니다:

python
# readable_numbers.py
# These are all the same number
million = 1000000
million = 1_000_000  # Much easier to read!
 
# Works with any size
population = 8_000_000_000
national_debt = 31_000_000_000_000
 
print(million)      # Output: 1000000 (underscores not shown in output)
print(population)   # Output: 8000000000

또한 특수 접두사를 사용해 다른 진법의 정수도 쓸 수 있습니다:

python
# number_bases.py
# Binary (base 2) - prefix 0b
binary = 0b1010  # This is 10 in decimal
print(binary)  # Output: 10
 
# Octal (base 8) - prefix 0o
octal = 0o12  # This is 10 in decimal
print(octal)  # Output: 10
 
# Hexadecimal (base 16) - prefix 0x
hexadecimal = 0xFF  # This is 255 in decimal
print(hexadecimal)  # Output: 255

이런 다른 진법 표현은 웹 디자인에서 색상 값을 다루거나, 저수준 프로그래밍을 할 때 유용합니다. 하지만 일상적인 프로그래밍에서는 대부분 일반적인 10진법 정수를 사용하게 됩니다.

3.4.2) 부동소수점 수 (float)

부동소수점 수 (floating-point number) 타입 float는 소수점을 가진 수입니다. float는 반드시 정수가 아닐 수도 있는 실수(real number)를 표현하는 데 사용됩니다:

python
# floats.py
# Numbers with decimal points
price = 19.99
temperature = 98.6
pi = 3.14159
 
# Very small numbers
electron_mass = 0.00000000000000000000000000000091093837
 
# Very large numbers
speed_of_light = 299792458.0
 
print(price)           # Output: 19.99
print(temperature)     # Output: 98.6
print(electron_mass)   # Output: 9.1093837e-31 (scientific notation)
print(speed_of_light)  # Output: 299792458.0

아주 작거나 아주 큰 부동소수점 수는 과학적 표기법 (scientific notation) 으로 표시되는 것에 주목하세요. 9.1093837e-31 표기는 "9.1093837 × 10⁻³¹" 또는 "9.1093837을 10의 31제곱으로 나눈 것"을 의미합니다.

과학적 표기법을 사용해 직접 float를 작성할 수도 있습니다:

python
# scientific_notation.py
# These are equivalent
avogadro = 602214076000000000000000.0
avogadro = 6.02214076e23  # Much more readable!
 
# Small numbers
planck = 0.000000000000000000000000000000000662607015
planck = 6.62607015e-34  # Much more readable!
 
print(avogadro)  # Output: 6.02214076e+23
print(planck)    # Output: 6.62607015e-34

여기서 e(또는 E)는 "지수 (exponent)"를 의미합니다. e 뒤에 오는 숫자는 소수점을 몇 자리 이동할지를 나타냅니다(양수면 오른쪽, 음수면 왼쪽).

3.4.3) 정수 vs float: 중요한 차이점

정수와 float는 모두 숫자를 표현하지만, 중요한 차이점이 있습니다.

1. 정밀도와 표현 방식:

정수는 정확합니다. 값 42는 근사값이 아니라 정확히 42입니다. 반면 float는 컴퓨터가 이진수로 소수점을 표현하는 방식 때문에 근사값입니다:

python
# float_precision.py
# This might surprise you!
result = 0.1 + 0.2
print(result)  # Output: 0.30000000000000004
 
# The result isn't exactly 0.3 due to floating-point representation
print(result == 0.3)  # Output: False

이것은 버그가 아니라, 컴퓨터가 10진수 소수를 표현하는 근본적인 한계입니다. 4장 4.10절에서 이 부분을 더 자세히 다루겠지만, 지금은 float 계산이 완벽히 정확하지 않을 수 있다는 점만 알아두면 됩니다.

2. 연산과 결과:

정수와 float로 연산을 수행할 때, Python은 특정 규칙을 따릅니다:

python
# int_float_operations.py
# Integer operations
int_result = 10 + 5
print(int_result, type(int_result))  # Output: 15 <class 'int'>
 
# Float operations
float_result = 10.0 + 5.0
print(float_result, type(float_result))  # Output: 15.0 <class 'float'>
 
# Mixed operations: result is always float
mixed_result = 10 + 5.0
print(mixed_result, type(mixed_result))  # Output: 15.0 <class 'float'>
 
# Division always returns float, even with integers
division_result = 10 / 5
print(division_result, type(division_result))  # Output: 2.0 <class 'float'>

핵심 규칙은 다음과 같습니다. float가 한 번이라도 연산에 참여하면 결과는 항상 float입니다. float는 정수보다 더 넓은 범위(정수가 아닌 수까지)를 표현할 수 있기 때문에, Python은 결과를 더 일반적인 타입인 float로 "승격"합니다.

3. 메모리와 성능:

정수는 float보다 적은 메모리를 사용하고, 계산도 더 빠릅니다. 대부분의 프로그램에서는 이 차이가 눈에 띄지 않지만, 성능이 매우 중요한 애플리케이션이나 아주 큰 데이터를 다룰 때는 차이가 날 수 있습니다.

3.4.4) int를 쓸 때와 float를 쓸 때

정수와 float 중 어느 것을 써야 할지에 대한 실용적인 가이드는 다음과 같습니다.

다음과 같은 경우에는 정수(int)를 사용합니다:

  • 개별 항목을 세는 경우(사람 수, 물건 개수, 반복 횟수)
  • 나눌 수 없는 정확한 양(학생 수, 클릭 수 등)을 표현할 때
  • 시퀀스(리스트 등)의 인덱스나 위치를 나타낼 때
  • 정확한 산술이 필요한 경우
python
# use_integers.py
student_count = 30  # Can't have 30.5 students
page_number = 42    # Can't be on page 42.7
loop_counter = 0    # Counting iterations

다음과 같은 경우에는 float를 사용합니다:

  • 온도, 거리, 무게 같은 측정값을 표현할 때
  • 금액을 다룰 때(다만 정밀도 문제에 주의해야 합니다. 4장에서 다룹니다)
  • 비율, 퍼센트, 평균값을 계산할 때
  • 어느 정도의 근사값이 허용될 때
python
# use_floats.py
temperature = 72.5     # Temperature can be fractional
price = 19.99          # Money amounts have cents
average_score = 87.3   # Averages are often fractional
percentage = 0.15      # 15% as a decimal

3.5) 문자열과 불리언 리터럴(간단한 미리보기)

이 절에서는 두 가지 기본 데이터 타입인 문자열(string)과 불리언(boolean)을 간단히 소개합니다. 문자열은 5장과 6장에서 훨씬 자세히 다루고, 불리언은 7장에서 자세히 다루겠지만, 간단한 프로그램을 작성하기 위해서라도 지금 기본적인 이해가 필요합니다.

3.5.1) 문자열 기초

문자열 (string), 타입 str는 문자들의 시퀀스, 즉 텍스트입니다. 문자열은 텍스트를 따옴표로 감싸서 만듭니다. Python에서는 작은따옴표(')와 큰따옴표(")를 모두 허용합니다:

python
# string_basics.py
# Single quotes
name = 'Alice'
message = 'Hello, World!'
 
# Double quotes (exactly equivalent)
name = "Alice"
message = "Hello, World!"
 
# Print them
print(name)     # Output: Alice
print(message)  # Output: Hello, World!
print(type(name))  # Output: <class 'str'>

작은따옴표와 큰따옴표는 완전히 동일하게 동작합니다. 어느 쪽을 쓸지 선택해서 코드 전체에서 일관되게 사용하면 됩니다. 많은 Python 개발자들이 다른 언어와의 일관성을 위해 큰따옴표를 선호하지만, 작은따옴표를 써도 전혀 문제 없습니다.

둘 다 있는 이유는? 문자열 안에 따옴표가 포함될 때 편리하기 때문입니다:

python
# quotes_in_strings.py
# Use double quotes when string contains single quotes
sentence = "It's a beautiful day!"
print(sentence)  # Output: It's a beautiful day!
 
# Use single quotes when string contains double quotes
speech = 'She said, "Hello!"'
print(speech)  # Output: She said, "Hello!"'
 
# Or use escape sequences (we'll learn more in Chapter 5)
sentence = 'It\'s a beautiful day!'  # \' means a literal single quote
speech = "She said, \"Hello!\""     # \" means a literal double quote

문자열은 아무 문자도 포함하지 않는 빈 문자열일 수도 있습니다:

python
# empty_string.py
empty = ""
also_empty = ''
 
print(empty)            # Output: (nothing—it's empty!)
print(len(empty))       # Output: 0 (we'll learn about len() later)
print(type(empty))      # Output: <class 'str'>

+ 연산자를 사용해 문자열을 결합(연결, concatenation)할 수 있습니다:

python
# string_concatenation.py
first_name = "John"
last_name = "Doe"
full_name = first_name + " " + last_name
print(full_name)  # Output: John Doe
 
# Be careful: you can't concatenate strings and numbers directly
age = 25
# message = "I am " + age + " years old"  # Error: TypeError
 
# Convert the number to a string first
message = "I am " + str(age) + " years old"
print(message)  # Output: I am 25 years old

문자열은 5장과 6장에서 이스케이프 시퀀스, 문자열 메서드, 포맷팅, 텍스트 처리 등과 함께 훨씬 자세히 다룰 것입니다. 지금은 문자열이 텍스트를 표현하며 따옴표로 만든다는 점만 기억하면 됩니다.

3.5.2) 불리언 기초

불리언 (boolean), 타입 bool은 논리 값으로 True 또는 False 두 가지 중 하나만 가질 수 있습니다. 이 값들은 논리 연산에서 참과 거짓을 표현하는 데 사용됩니다:

python
# boolean_basics.py
# Boolean literals
is_sunny = True
is_raining = False
 
print(is_sunny)         # Output: True
print(is_raining)       # Output: False
print(type(is_sunny))   # Output: <class 'bool'>

중요: 불리언 값 TrueFalse는 반드시 여기 보이는 것처럼 정확히 대문자를 사용해야 합니다. Python은 대소문자를 구분하므로 true, TRUE, false, FALSE는 동작하지 않습니다:

python
# boolean_case.py
correct = True    # Correct
# wrong = true    # Error: NameError: name 'true' is not defined
# wrong = TRUE    # Error: NameError: name 'TRUE' is not defined

불리언은 보통 비교 연산이나 논리 연산의 결과로 생깁니다:

python
# boolean_from_comparisons.py
age = 25
 
# Comparison operators produce boolean results
is_adult = age >= 18
print(is_adult)  # Output: True
 
is_senior = age >= 65
print(is_senior)  # Output: False
 
# You can use booleans in conditions (we'll learn more in Chapter 8)
if is_adult:
    print("You can vote!")  # Output: You can vote!
 
if is_senior:
    print("You get a senior discount!")  # (no output—condition is False)

불리언을 만들어 내는 대표적인 비교 연산자는 다음과 같습니다:

  • == : 같다
  • != : 같지 않다
  • < : 작다
  • > : 크다
  • <= : 작거나 같다
  • >= : 크거나 같다
python
# comparison_operators.py
x = 10
y = 20
 
print(x == y)   # Output: False (10 is not equal to 20)
print(x != y)   # Output: True (10 is not equal to 20)
print(x < y)    # Output: True (10 is less than 20)
print(x > y)    # Output: False (10 is not greater than 20)
print(x <= 10)  # Output: True (10 is less than or equal to 10)
print(y >= 20)  # Output: True (20 is greater than or equal to 20)

중요한 점: =(할당)과 ==(비교)를 혼동하지 마세요.

  • x = 10 은 "x에 10을 할당한다"는 뜻입니다.
  • x == 10 은 "x가 10과 같은지 확인한다"는 뜻이며, 결과로 True 또는 False를 돌려줍니다.
python
# assignment_vs_comparison.py
x = 10        # Assignment: x now refers to 10
result = (x == 10)  # Comparison: is x equal to 10?
print(result)  # Output: True
 
# This is a common mistake for beginners:
# if x = 10:  # Error: SyntaxError (can't use assignment in if condition)
if x == 10:   # Correct: comparison
    print("x is 10")  # Output: x is 10

불리언은 7장에서 and, or, not 같은 논리 연산자, 진릿값과 거짓값, Python이 조건문에서 불리언을 사용하는 방법 등과 함께 훨씬 더 자세히 다룰 것입니다. 지금은 불리언이 True/False 값을 표현하며, 보통 비교의 결과로 생긴다는 점만 기억하면 됩니다.

3.5.3) 문자열과 불리언을 함께 사용하는 예

문자열과 불리언이 함께 어떻게 동작하는지 간단한 실용 예제를 통해 보겠습니다:

python
# strings_booleans_example.py
# Get user input
name = input("What is your name? ")
age_input = input("What is your age? ")
 
# Convert age to integer
age = int(age_input)
 
# Create boolean conditions
is_adult = age >= 18
is_child = age < 13
 
# Build messages using strings
if is_adult:
    status = "adult"
else:
    status = "minor"
 
# Combine everything in output
print("Hello, " + name + "!")
print("You are an " + status + ".")
 
if is_child:
    print("You are a child.")
 
# When user enters "Alice" and "16":
# Output: Hello, Alice!
# Output: You are a minor.

이 예시는 서로 다른 데이터 타입이 함께 동작하는 방식을 보여 줍니다. 텍스트에는 문자열, 숫자에는 정수, 논리적인 결정에는 불리언을 사용합니다. 이런 타입 간 상호 작용은 모든 프로그래밍의 기본입니다.

3.6) None 값과 그 활용

3.6.1) None이란?

Python에는 None이라는 특수 값이 있습니다(타입은 NoneType). 이 값은 값의 부재를 나타냅니다. "여기에는 아무것도 없다" 또는 "아직 값이 없다"는 의미를 표현하는 Python의 방식입니다.

python
# none_basics.py
result = None
print(result)        # Output: None
print(type(result))  # Output: <class 'NoneType'>

None은 0이나 빈 문자열, False와 다릅니다. "값이 없다"라는 뜻을 가진 완전히 별개의 값입니다:

python
# none_vs_others.py
x = None
y = 0
z = ""
w = False
 
print(x)  # Output: None
print(y)  # Output: 0
print(z)  # Output: (empty—nothing prints)
print(w)  # Output: False
 
# They're all different types
print(type(x))  # Output: <class 'NoneType'>
print(type(y))  # Output: <class 'int'>
print(type(z))  # Output: <class 'str'>
print(type(w))  # Output: <class 'bool'>

3.6.2) None이 사용되는 상황

None은 여러 흔한 상황에서 등장합니다.

1. 나중에 값을 할당할 변수의 자리표시자로 사용:

python
# none_placeholder.py
# Initialize variables that will be assigned later
user_name = None
user_age = None
 
# Later in the program, after getting user input:
user_name = input("Enter your name: ")
user_age = int(input("Enter your age: "))
 
print("Name:", user_name)
print("Age:", user_age)

2. 값을 명시적으로 반환하지 않는 함수의 기본 반환값으로 사용:

19장에서 배우게 될 함수는 값을 반환할 수 있습니다. 함수가 명시적으로 아무 것도 반환하지 않으면, Python은 자동으로 None을 반환합니다:

python
# none_from_function.py
# The print() function returns None
result = print("Hello!")  # Output: Hello!
print(result)             # Output: None
print(type(result))       # Output: <class 'NoneType'>

이것이 다소 이상하게 느껴질 수 있지만, 유용한 특성입니다. 함수가 "의미 있는 값이 없다"는 상황일지라도, 항상 무엇인가를 반환한다는 뜻이기 때문입니다.

3. 선택적이거나 누락된 데이터를 표현할 때:

python
# none_optional.py
# Representing optional middle name
first_name = "John"
middle_name = None  # No middle name
last_name = "Doe"
 
if middle_name is None:
    full_name = first_name + " " + last_name
else:
    full_name = first_name + " " + middle_name + " " + last_name
 
print(full_name)  # Output: John Doe

3.6.3) None인지 확인하기

값이 None인지 확인할 때는 ==가 아니라 is 연산자를 사용합니다:

python
# checking_none.py
value = None
 
# Correct way: use 'is'
if value is None:
    print("Value is None")  # Output: Value is None
 
# Also correct: use 'is not'
if value is not None:
    print("Value has a value")
else:
    print("Value is None")  # Output: Value is None
 
# While == works, 'is' is preferred for None
if value == None:  # This works but is not idiomatic Python
    print("Value is None")  # Output: Value is None

== 대신 is를 사용할까요? is 연산자는 두 이름이 메모리의 같은 객체를 가리키는지 검사합니다(자세한 내용은 17장에서 다룹니다). None 객체는 Python에 하나만 존재하므로, is를 사용하는 것이 더 효율적이고 정확합니다. is None을 사용하는 것은 Python에서 널리 쓰이는 관용구입니다.

3.6.4) 실제 코드에서의 None 활용

다음은 실제 프로그램에서 None이 유용하게 쓰이는 예입니다:

python
# none_practical.py
# Simulate looking up a user's age
# (In real programs, we'd use functions and dictionaries from later chapters)
 
user_name = input("Enter a name (Alice, Bob, or Charlie): ")
 
# Check each name and assign age or None
if user_name == "Alice":
    user_age = 25
elif user_name == "Bob":
    user_age = 30
elif user_name == "Charlie":
    user_age = 35
else:
    user_age = None  # User not found
 
# Check if we found the user
if user_age is not None:
    print(user_name, "is", user_age, "years old")
else:
    print(user_name, "not found")
 
# When user enters "Alice":
# Output: Alice is 25 years old
# When user enters "David":
# Output: David not found

이 예시에서 None은 "사용자를 찾지 못했다"를 명확하게 나타냅니다. 나이가 0인 사용자(신생아 같은)는 유효한 나이이므로, 그와 구분됩니다.

3.6.5) None vs 빈 값

None과 빈 값을 구분하는 것이 중요합니다:

python
# none_vs_empty.py
# These are all different
nothing = None
zero = 0
empty_string = ""
# Note: We'll learn about lists in Chapter 13
# empty_list = []
 
print(nothing is None)       # Output: True
print(zero is None)          # Output: False
print(empty_string is None)  # Output: False
 
# None means "no value"
# 0 means "the number zero"
# "" means "text with no characters"

각각은 서로 다른 개념을 나타냅니다:

  • None: 값의 부재
  • 0: 특정 숫자 값(0)
  • "": 존재하지만 안에 문자가 하나도 없는 문자열

이 차이를 이해하면 더 명확하고 올바른 프로그램을 작성하는 데 도움이 됩니다.

3.7) int(), float(), str()로 기본 형 변환하기

3.7.1) 형 변환이 필요한 이유

이미 보았듯이 Python에는 각 타입마다 허용되는 연산 규칙이 엄격하게 정해져 있습니다. 숫자와 문자열을 더할 수 없고, 문자열을 float와 곱할 수 없으며, 텍스트에 직접 수학 연산을 할 수도 없습니다. 어떤 값을 다른 타입으로 사용해야 할 때는, 명시적으로 변환해야 합니다.

형 변환(또는 타입 캐스팅, type casting)은 값을 한 타입에서 다른 타입으로 바꾸는 과정입니다. Python은 가장 흔한 변환을 위해 다음과 같은 내장 함수를 제공합니다:

  • int(): 정수로 변환
  • float(): 부동소수점 수로 변환
  • str(): 문자열로 변환

각각을 자세히 살펴보겠습니다.

3.7.2) int()로 정수로 변환하기

int() 함수는 값을 정수로 변환합니다. 주요 사용 사례는 다음과 같습니다.

float를 정수로 변환하기:

python
# float_to_int.py
# int() truncates (cuts off) the decimal part
x = int(3.14)
y = int(3.99)
z = int(-2.7)
 
print(x)  # Output: 3 (not 4—it doesn't round!)
print(y)  # Output: 3 (not 4—it truncates!)
print(z)  # Output: -2 (truncates toward zero)

중요: int()는 반올림하지 않고 단순히 소수 부분을 잘라냅니다(0을 향해 잘라냅니다). 많은 초보자들이 int(3.9)가 4를 반환하길 기대하는데, 실제로는 3을 반환합니다.

문자열을 정수로 변환하기:

사용자 입력을 다룰 때 매우 흔하게 사용하는 방법입니다:

python
# string_to_int.py
# Convert string containing a number
age_str = "25"
age_int = int(age_str)
 
print(age_str, type(age_str))  # Output: 25 <class 'str'>
print(age_int, type(age_int))  # Output: 25 <class 'int'>
 
# Now we can do math with it
next_year = age_int + 1
print("Next year:", next_year)  # Output: Next year: 26
 
# Practical example with input()
user_age = int(input("Enter your age: "))
print("In 10 years, you'll be", user_age + 10)

잘못된 변환은 어떻게 되는가?

정수가 아닌 문자열을 정수로 변환하려 하면 Python은 ValueError를 발생시킵니다:

python
# invalid_int_conversion.py
# These work
print(int("123"))    # Output: 123
print(int("-456"))   # Output: -456
print(int("  789 ")) # Output: 789 (whitespace is ignored)
 
# These don't work
# print(int("12.5"))   # Error: ValueError: invalid literal for int()
# print(int("hello"))  # Error: ValueError: invalid literal for int()
# print(int("12 34"))  # Error: ValueError: invalid literal for int()

이러한 오류를 안전하게 처리하는 방법은 27장에서 예외 처리(exception handling)를 배우면서 다룹니다. 지금은 문자열이 유효한 정수 표현인지 확인한 후 변환해야 한다는 점만 알아두면 됩니다.

불리언을 정수로 변환하기:

불리언을 정수로 변환하면 True1, False0이 됩니다:

python
# bool_to_int.py
print(int(True))   # Output: 1
print(int(False))  # Output: 0
 
# This is sometimes useful in calculations
is_premium = True
is_student = False
 
# Calculate discount (10% for premium, 5% for students)
discount = int(is_premium) * 0.10 + int(is_student) * 0.05
print("Discount:", discount)  # Output: Discount: 0.1

하지만 불리언을 직접 산술에 사용하는 것은 코드 가독성을 떨어뜨리기 때문에 일반적으로는 권장되지 않습니다. 이 주제는 7장에서 더 이야기하겠습니다.

3.7.3) float()로 부동소수점 수로 변환하기

float() 함수는 값을 부동소수점 수로 변환합니다.

정수를 float로 변환하기:

python
# int_to_float.py
x = float(42)
y = float(-17)
z = float(0)
 
print(x, type(x))  # Output: 42.0 <class 'float'>
print(y, type(y))  # Output: -17.0 <class 'float'>
print(z, type(z))  # Output: 0.0 <class 'float'>

문자열을 float로 변환하기:

python
# string_to_float.py
# Convert string containing decimal number
price_str = "19.99"
price_float = float(price_str)
 
print(price_str, type(price_str))    # Output: 19.99 <class 'str'>
print(price_float, type(price_float))  # Output: 19.99 <class 'float'>
 
# Strings without decimal points work too
x = float("42")
print(x, type(x))  # Output: 42.0 <class 'float'>
 
# Scientific notation strings work
big = float("1.5e10")
print(big)  # Output: 15000000000.0

잘못된 변환:

int()와 마찬가지로, float()도 잘못된 문자열에 대해 ValueError를 발생시킵니다:

python
# invalid_float_conversion.py
# These work
print(float("3.14"))      # Output: 3.14
print(float("  2.5  "))   # Output: 2.5 (whitespace ignored)
print(float("-0.5"))      # Output: -0.5
print(float("inf"))       # Output: inf (infinity)
 
# These don't work
# print(float("hello"))   # Error: ValueError
# print(float("1.2.3"))   # Error: ValueError

불리언을 float로 변환하기:

python
# bool_to_float.py
print(float(True))   # Output: 1.0
print(float(False))  # Output: 0.0

3.7.4) str()로 문자열로 변환하기

str() 함수는 어떤 값이든 그 값의 문자열 표현으로 변환합니다.

숫자를 문자열로 변환하기:

python
# number_to_string.py
# Convert integer
age = 25
age_str = str(age)
print(age_str, type(age_str))  # Output: 25 <class 'str'>
 
# Convert float
price = 19.99
price_str = str(price)
print(price_str, type(price_str))  # Output: 19.99 <class 'str'>
 
# Now we can concatenate with other strings
message = "The price is $" + price_str
print(message)  # Output: The price is $19.99

문자열을 조합해 메시지를 만들 때 특히 유용합니다:

python
# building_messages.py
name = "Alice"
age = 25
height = 5.6
 
# Without str(), this would cause an error
# message = "Name: " + name + ", Age: " + age  # Error!
 
# With str(), it works
message = "Name: " + name + ", Age: " + str(age) + ", Height: " + str(height)
print(message)  # Output: Name: Alice, Age: 25, Height: 5.6

불리언을 문자열로 변환하기:

python
# bool_to_string.py
is_valid = True
is_error = False
 
print(str(is_valid))  # Output: True
print(str(is_error))  # Output: False
 
# Useful in messages
status = "Status: " + str(is_valid)
print(status)  # Output: Status: True

None을 문자열로 변환하기:

python
# none_to_string.py
value = None
value_str = str(value)
print(value_str)        # Output: None
print(type(value_str))  # Output: <class 'str'>
 
# The string "None" is different from the value None
print(value is None)      # Output: True
print(value_str is None)  # Output: False
print(value_str == "None")  # Output: True

3.7.5) 실전에서의 변환 패턴

다음은 흔한 변환 패턴을 한 번에 보여 주는 예입니다:

python
# conversion_patterns.py
# Get user input (always strings)
name = input("Enter your name: ")
age_str = input("Enter your age: ")
height_str = input("Enter your height in feet: ")
 
# Convert to appropriate types
age = int(age_str)
height = float(height_str)
 
# Perform calculations
age_in_months = age * 12
height_in_inches = height * 12
 
# Convert back to strings for output
print("Hello, " + name + "!")
print("You are " + str(age_in_months) + " months old.")
print("Your height is " + str(height_in_inches) + " inches.")
 
# Alternative: use multiple arguments to print() (no conversion needed)
print("Hello,", name + "!")
print("You are", age_in_months, "months old.")
print("Your height is", height_in_inches, "inches.")
 
# When user enters "Alice", "25", and "5.5":
# Output: Hello, Alice!
# Output: You are 300 months old.
# Output: Your height is 66.0 inches.
# Output: Hello, Alice!
# Output: You are 300 months old.
# Output: Your height is 66.0 inches.

,로 구분된 여러 인자를 print()에 전달하면, print()가 값을 자동으로 문자열로 변환하고 사이에 공백을 넣어 줍니다. 직접 str()로 변환하고 +로 이어 붙이는 것보다 더 편리한 경우가 많습니다.

3.7.6) 변환 흐름 다이어그램

흔한 타입 변환을 시각적으로 나타내면 다음과 같습니다:

float

int truncates

str

str

int

float

str

int

float

int

float

str

bool

변환에 대한 핵심 포인트:

  • int → float: 항상 안전하며 .0이 붙습니다.
  • float → int: 소수 부분을 잘라냅니다(반올림이 아님).
  • 어느 타입 → str: 항상 안전하며 텍스트 표현으로 바꿉니다.
  • str → int/float: 문자열이 유효한 숫자 표현일 때만 동작합니다.
  • bool → int/float: True는 1/1.0, False는 0/0.0이 됩니다.

3.7.7) 흔한 변환 실수

형 변환과 관련해 초보자들이 자주 하는 실수는 다음과 같습니다.

실수 1: 사용자 입력을 변환하지 않음

python
# conversion_mistake1.py
# Wrong: trying to do math with string
age = input("Enter your age: ")
# next_year = age + 1  # Error: TypeError
 
# Right: convert first
age = int(input("Enter your age: "))
next_year = age + 1
print("Next year:", next_year)

실수 2: 필요하지 않은데도 변환함

python
# conversion_mistake2.py
# Unnecessary: print() handles conversion automatically
age = 25
print("Age:", age)  # This works fine
 
# No need for:
print("Age:", str(age))  # Unnecessary str() conversion

실수 3: 잘못된 문자열을 변환하려 함

python
# conversion_mistake3.py
# This will crash if user enters non-numeric input
# age = int(input("Enter your age: "))  # Crashes on "twenty"
 
# We'll learn to handle this safely in Chapter 27

실수 4: int()가 반올림해 줄 거라고 기대함

python
# conversion_mistake4.py
# Wrong expectation: int() truncates, doesn't round
x = int(3.7)
print(x)  # Output: 3 (not 4!)
 
# If you want rounding, use round()
x = round(3.7)
print(x)  # Output: 4

3.8) str()와 repr()로 문자열 표현 얻기

3.8.1) str()와 repr()의 차이

Python은 객체의 문자열 표현을 얻는 두 가지 방법인 str()repr()을 제공합니다. 둘은 비슷해 보이지만 목적이 다릅니다:

  • str(): 사람이 읽기 좋은, 보기 좋은 문자열 표현을 만듭니다.
  • repr(): 개발자를 위한, 모호하지 않은 "공식적인" 문자열 표현을 만듭니다.

숫자처럼 단순한 타입에서는 둘의 결과가 자주 같지만, 다른 타입에서는 크게 다를 수 있습니다:

python
# str_vs_repr.py
# For numbers, they're usually the same
x = 42
print(str(x))   # Output: 42
print(repr(x))  # Output: 42
 
# For strings, they differ
text = "Hello"
print(str(text))   # Output: Hello
print(repr(text))  # Output: 'Hello' (includes quotes!)
 
# For strings with special characters, repr() shows escape sequences
message = "Hello\nWorld"
print(str(message))   # Output: Hello
                      #         World (newline is interpreted)
print(repr(message))  # Output: 'Hello\nWorld' (shows the \n literally)

3.8.2) str()를 사용할 때

str()는 최종 사용자에게 보여 줄 읽기 쉬운 표현이 필요할 때 사용합니다:

python
# using_str.py
price = 19.99
quantity = 3
 
# Create user-friendly messages
message = "Total: $" + str(price * quantity)
print(message)  # Output: Total: $59.97
 
# str() is what print() uses automatically
print("Total: $", price * quantity)  # Output: Total: $ 59.97

str()는 사람에게 의미 있는 출력을 만들도록 설계되었습니다. 기술적인 세부 사항 일부가 생략되더라도, 사람이 읽기 쉽게 만드는 것이 우선입니다. print()를 호출하면 Python은 인자에 대해 자동으로 str()를 호출합니다.

3.8.3) repr()를 사용할 때

repr()는 디버깅이 필요할 때처럼 모호하지 않은 표현이 필요할 때 사용합니다:

python
# using_repr.py
# Debugging: see exactly what's in a variable
text = "Hello\nWorld"
print("Debug info:", repr(text))  # Output: Debug info: 'Hello\nWorld'
 
# Compare two similar-looking strings
str1 = "42"
str2 = "42 "  # Has trailing space
 
print(str1)       # Output: 42
print(str2)       # Output: 42  (space not obvious)
print(repr(str1)) # Output: '42'
print(repr(str2)) # Output: '42 ' (space is visible!)

repr()는 일반 출력에서는 보이지 않는 부분까지 포함해, Python이 실제로 보고 있는 그대로를 보여 주도록 설계되었습니다. 이 때문에 디버깅에서 매우 중요합니다.

3.8.4) repr()의 목표: 다시 만들 수 있는 표현

이상적으로 repr()는 Python 인터프리터에 다시 넘겼을 때 원래 객체를 재생성할 수 있는 문자열을 반환해야 합니다. 기본 타입들에 대해서는 실제로 이렇게 동작합니다:

python
# repr_recreate.py
# For numbers
x = 42
x_repr = repr(x)
print(x_repr)  # Output: 42
 
# You could use this to recreate x
x_recreated = eval(x_repr)  # eval() evaluates a string as Python code
print(x_recreated)  # Output: 42
 
# For strings
text = "Hello"
text_repr = repr(text)
print(text_repr)  # Output: 'Hello'
 
# This could recreate the string
text_recreated = eval(text_repr)
print(text_recreated)  # Output: Hello

중요한 주의점: eval() 함수는 문자열을 Python 코드처럼 실행합니다. 여기서는 repr()의 목적을 설명하기 위해 언급했지만, 신뢰할 수 없는 입력에 대해서는 절대 eval()을 사용하지 마세요. 보안상 매우 위험합니다. 더 안전한 대안은 이후 장들에서 다룹니다.

3.8.5) str()와 repr()의 실제 예

예 1: 문자열 문제 디버깅

python
# debugging_strings.py
# User input might have unexpected whitespace
user_input = "  Alice  "
 
print("User entered:", user_input)         # Output: User entered:   Alice  
print("Debug view:", repr(user_input))     # Output: Debug view: '  Alice  '
 
# Now the extra spaces are obvious!
cleaned = user_input.strip()  # Remove leading/trailing whitespace
print("Cleaned:", repr(cleaned))  # Output: Cleaned: 'Alice'

예 2: 서로 다른 타입 비교

python
# comparing_types.py
# These look similar but are different
num = 42
text = "42"
 
print("Number:", num)       # Output: Number: 42
print("Text:", text)        # Output: Text: 42
 
print("Number repr:", repr(num))   # Output: Number repr: 42
print("Text repr:", repr(text))    # Output: Text repr: '42'
 
# repr() makes the difference clear
print("Are they equal?", num == text)  # Output: Are they equal? False

3.8.6) 우리가 배운 타입들에서의 str()와 repr()

지금까지 배운 타입들에 대해 str()repr()가 어떻게 동작하는지 살펴보겠습니다:

python
# str_repr_types.py
# Integers
x = 42
print("int str:", str(x))    # Output: int str: 42
print("int repr:", repr(x))  # Output: int repr: 42
 
# Floats
y = 3.14159
print("float str:", str(y))   # Output: float str: 3.14159
print("float repr:", repr(y)) # Output: float repr: 3.14159
 
# Booleans
b = True
print("bool str:", str(b))   # Output: bool str: True
print("bool repr:", repr(b)) # Output: bool repr: True
 
# None
n = None
print("None str:", str(n))   # Output: None str: None
print("None repr:", repr(n)) # Output: None repr: None
 
# Strings (where they differ most)
s = "Hello\nWorld"
print("string str:", str(s))   # Output: string str: Hello
                                #                     World
print("string repr:", repr(s)) # Output: string repr: 'Hello\nWorld'

3.8.7) 핵심 정리

str()를 사용할 때:

  • 최종 사용자에게 보여 줄 출력을 만들 때
  • 사용자 대상 메시지를 만들 때
  • 데이터를 화면에 보기 좋게 표시할 때
  • 읽기 쉽고 친근한 출력이 필요할 때

repr()를 사용할 때:

  • 코드를 디버깅할 때
  • 기술적인 정보를 로깅할 때
  • 변수 안에 무엇이 들어 있는지 정확히 보고 싶을 때
  • 모호하지 않은 표현이 필요할 때

기억할 점:

  • print()는 인자에 대해 자동으로 str()를 사용합니다.
  • 대부분의 기본 타입에서는 str()repr()의 결과가 비슷합니다.
  • 문자열의 경우, repr()는 따옴표를 포함하고 이스케이프 시퀀스를 그대로 보여 줍니다.
  • repr()는 모호하지 않고 (이상적으로는) 다시 생성 가능한 표현을 만들도록 설계되었습니다.

장 요약

이 장에서는 Python에서 변수와 데이터 타입의 기본 개념을 배웠습니다. 주요 내용을 정리해 보겠습니다.

변수:

  • 변수는 메모리에 있는 값을 가리키는 이름입니다.
  • variable_name = value 형식의 할당을 통해 만듭니다.
  • 언제든지 새 값으로 재할당할 수 있습니다.
  • 이름은 규칙을 따라야 하며, 관례를 따르면 더 좋습니다.
  • 설명적인 이름을 사용하면 코드가 스스로 설명되도록(자기 문서화) 만들 수 있습니다.

데이터 타입:

  • Python의 모든 값에는 타입이 있습니다.
  • type() 함수로 값의 타입을 확인할 수 있습니다.
  • Python은 동적 타이핑을 사용하므로, 변수는 시간에 따라 다른 타입의 값을 가리킬 수 있습니다.
  • 타입마다 지원하는 연산이 다릅니다.

기본 타입들:

  • int: 전체 수(양수, 음수, 0), 크기 제한 거의 없음
  • float: 소수점을 가진 수, 표현 방식 때문에 정밀도 한계가 있을 수 있음
  • str: 따옴표로 감싼 텍스트(작은따옴표 또는 큰따옴표)
  • bool: 논리 값 True 또는 False
  • None: 값의 부재를 나타내는 특수 값

형 변환:

  • int(): 정수로 변환(소수 부분 잘라냄, 문자열 파싱)
  • float(): 부동소수점 수로 변환
  • str(): 문자열로 변환(항상 동작)
  • 잘못된 입력에 대해 변환은 실패할 수 있으며, ValueError를 발생시킵니다.

문자열 표현:

  • str(): 최종 사용자를 위한, 사람이 읽기 좋은 표현
  • repr(): 개발자/디버깅용의, 모호하지 않은 표현
  • print()는 인자에 대해 자동으로 str()를 사용합니다.

이 개념들은 Python의 모든 것의 기초입니다. 여러분이 작성하는 모든 프로그램은 데이터를 저장하기 위해 변수를 사용할 것이며, 데이터 타입을 이해하면 어떤 연산이 동작하고 어떤 오류가 발생할지 예측할 수 있습니다.

다음 장에서는 이 기초 위에 숫자를 다루는 방법을 더 깊이 탐구하겠습니다. 산술 연산, 연산자 우선순위, 흔한 숫자 패턴을 다루고, 계산을 수행하는 방법, 수학 함수 사용법, 부동소수점 산술의 특이점까지 알아보겠습니다.

© 2025. Primesoft Co., Ltd.
support@primesoft.ai