시작하기
Hello World & 주석
Python은 주석에 #를 사용하고 docstring에는 삼중 따옴표를 사용합니다. print() 함수는 sep과 end 매개변수를 지원하여 출력 형식을 사용자 정의할 수 있습니다. docstring은 help()와 __doc__를 통해 접근할 수 있는 문서로 사용됩니다.
# This is a single-line comment
"""
This is a
multi-line comment (docstring)
"""
print("Hello, World!") # print to stdout
print("A", "B", "C", sep="-") # A-B-C
print("No newline", end="") # suppress newline들여쓰기 & 코드 블록
대부분의 언어와 달리 Python은 코드 블록을 정의하기 위해 중괄호 대신 들여쓰기를 사용합니다. 일관성이 매우 중요합니다 — 탭과 공백을 혼용하면 SyntaxError가 발생합니다. PEP 8은 레벨당 4칸의 공백을 권장합니다.
# Python uses indentation (4 spaces) to define blocks
if True:
print("inside if")
if True:
print("nested block")
print("outside block")
# No braces! Indentation IS the syntax
def func():
x = 1
return x + 1입력 & 출력
input()은 stdin에서 문자열로 읽습니다 — 숫자가 필요할 때는 항상 변환하세요. 변환에는 int(), float() 등을 사용하세요. F-strings(Python 3.6+)는 문자열 형식을 지정하는 선호되는 방법입니다.
# input() always returns a string
name = input("Enter your name: ")
age = int(input("Enter your age: ")) # convert to int
print(f"Hello {name}, you are {age} years old")
# formatted output
print("Pi is approximately {:.2f}".format(3.14159))
print(f"{1000000:,}") # 1,000,000 with thousands separator다중 문장 & 줄 연속
한 줄에 여러 문장을 분리하기 위해 세미콜론을 사용합니다 (관용적인 Python에서는 드뭅니다). 긴 줄은 백슬래시로 연속할 수 있거나 (), [], {} 안에서 자동으로 연속됩니다. 가독성을 위해 암시적 연속을 선호하세요.
# multiple statements on one line (discouraged)
a = 1; b = 2; c = 3
# explicit line continuation
total = 1 + 2 + 3 + \
4 + 5 + 6
# implicit continuation inside brackets
nums = [
1, 2, 3,
4, 5, 6
]
result = (1 + 2
+ 3 + 4)Python 실행
Python 스크립트는 'python script.py'로 실행합니다. REPL은 대화형 실험을 허용합니다. python이 Python 2를 가리키는 시스템에서는 항상 python3를 사용하세요. shebang 줄은 Unix에서 스크립트를 실행 가능하게 만듭니다.
# Run a script
# $ python script.py
# Run interactively (REPL)
# $ python
# >>> 2 + 2
# 4
# Shebang line for Unix scripts
#!/usr/bin/env python3
# Check Python version
import sys
print(sys.version)
print(sys.version_info.major) # 3변수 & 데이터 타입
변수 & 동적 타이핑
Python은 동적 타이핑을 사용합니다 — 변수는 런타임에 타입을 변경할 수 있습니다. 확인에는 type()을, 검증에는 isinstance()를 사용하세요. Python 3.6+는 런타임 강제 없이 IDE 지원을 위한 타입 힌트(name: str = 'Alice')를 지원합니다.
# Python is dynamically typed - no declaration needed
name = "Alice" # str
age = 30 # int
height = 5.7 # float
is_active = True # bool
items = [1, 2, 3] # list
# Type checking
print(type(name)) # <class 'str'>
print(isinstance(age, int)) # True
# Multiple assignment
x, y, z = 1, 2, 3
a = b = 0 # chain assignment타입 힌트 (Python 3.6+)
타입 힌트는 코드 가독성을 높이고 IDE 자동완성과 mypy를 사용한 정적 분석을 가능하게 합니다. 런타임에 강제되지 않습니다 — Python은 여전히 동적으로 타입이 지정됩니다. None이 될 수 있는 값에는 Optional[X]를 사용하세요.
# Variable annotations
name: str = "Alice"
age: int = 30
scores: list[float] = [90.5, 85.0]
# Function annotations
def greet(name: str, times: int = 1) -> str:
return (f"Hi {name}! " * times).strip()
# Optional and Union
from typing import Optional, Union
def find(id: int) -> Optional[str]:
return "Alice" if id == 1 else None
# mypy for static type checking
# $ mypy script.py타입 변환
Python에는 내장 변환 함수가 있습니다: int(), float(), str(), bool(), list(), tuple(), set(), dict(). 거짓 값에는 0, '', [], {}, None, False가 포함됩니다. int()는 0을 향해 자르지만 round()는 은행가 반올림을 사용합니다.
# String to number
num_str = str(42) # "42"
num = int("42") # 42
float_num = float("3.14") # 3.14
# Number conversions
print(int(3.99)) # 3 (truncates toward zero)
print(int(-3.99)) # -3
print(round(3.14159, 2)) # 3.14
# Boolean conversion
print(bool(0)) # False
print(bool("")) # False
print(bool([])) # False
print(bool("anything")) # True
# Collection conversions
print(list("abc")) # ['a', 'b', 'c']
print(tuple([1, 2, 3])) # (1, 2, 3)
print(set([1, 1, 2])) # {1, 2}숫자 타입
Python 정수는 임의 정밀도를 가집니다 (오버플로우 없음). Float는 일반적인 정밀도 문제가 있는 IEEE 754 배정도입니다. 복소수는 내장되어 있습니다. 불리언은 int의 하위 클래스입니다 (True==1, False==0). 가독성을 위해 숫자 리터럴에 밑줄을 사용하세요.
# Integers (arbitrary precision)
big = 10 ** 100 # no overflow
print(type(big)) # <class 'int'>
# Floats (IEEE 754 double)
pi = 3.14159
print(0.1 + 0.2) # 0.30000000000000004
# Complex numbers
z = 3 + 4j
print(z.real, z.imag) # 3.0 4.0
print(abs(z)) # 5.0
# Boolean is subclass of int
print(isinstance(True, int)) # True
print(True + True) # 2
# Underscores in numbers (3.6+)
million = 1_000_000
binary = 0b_1010_1010상수 & 명명 규칙
Python에는 const 키워드가 없습니다 — ALL_CAPS 이름은 규칙에 의한 상수일 뿐입니다 (재할당을 막지 않음). PEP 8은 명명 규칙을 정의합니다: 변수/함수에는 snake_case, 클래스에는 PascalCase, 상수에는 ALL_CAPS. 선행 밑줄은 규칙상 'private'를 의미하고 이중 밑줄은 이름 장식을 트리거합니다.
# Python has no true constants - convention only
MAX_SIZE = 100 # ALL_CAPS for constants
PI = 3.14159
# Naming conventions (PEP 8)
variable_name = "snake_case" # variables, functions
ClassName = "PascalCase" # classes
CONSTANT_VALUE = 100 # constants
_private_var = "underscore prefix" # private (convention)
__name_mangled = "double underscore" # name mangling
# dunder names (reserved)
__name__, __main__, __init__문자열
문자열 메서드
문자열은 불변입니다 — 메서드는 새 문자열을 반환합니다. 찾지 못하면 find()는 -1을 반환하고 index()는 ValueError를 발생시킵니다. 검증에는 isalpha()/isdigit()/isalnum()을 사용하세요. str 클래스에는 40개 이상의 메서드가 있습니다 — dir(str)로 탐색하세요.
s = "Hello, World"
# Case operations
print(s.upper()) # HELLO, WORLD
print(s.lower()) # hello, world
print(s.title()) # Hello, World
print(s.capitalize()) # Hello, world
print(s.swapcase()) # hELLO, wORLD
# Search & replace
print(s.find("World")) # 7 (index, -1 if not found)
print(s.index("World")) # 7 (raises ValueError if not found)
print(s.replace("o", "0")) # Hell0, W0rld
print(s.count("l")) # 3
# Validation
print("abc".isalpha()) # True
print("123".isdigit()) # True
print(" ".isspace()) # True문자열 형식 지정
F-strings는 현대적이고 가장 빠르며 가장 읽기 쉬운 문자열 형식 지정 방법입니다. 콜론 뒤에 형식 사양을 지원합니다: 소수 2자리는 :.2f, 너비 10 우측 정렬은 :>10, 천 단위 구분자는 :,. 새 코드에서는 %-형식 지정을 피하세요.
name = "Alice"
age = 30
# f-strings (Python 3.6+) - PREFERRED
print(f"Hello, {name}! You are {age}.")
print(f"{name.upper()} is {age * 365} days old")
print(f"{3.14159:.2f}") # 3.14
print(f"{42:>10}") # right-align
print(f"{42:<10}") # left-align
print(f"{42:^10}") # center
print(f"{1000000:,}") # 1,000,000
# str.format() method
print("Hello, {}!".format(name))
print("{name} is {age}".format(name="Bob", age=25))
# Old style (avoid in new code)
print("Hello, %s!" % name)슬라이싱 & 인덱싱
Python 슬라이싱 구문 [start:stop:step]은 강력합니다 — stop은 배타적입니다. 음수 인덱스는 끝에서부터 셉니다. s[::-1]은 문자열을 뒤집는 관용적인 방법입니다. 슬라이싱은 안전합니다 — 범위를 벗어난 인덱스는 오류를 발생시키지 않고 빈 문자열을 반환합니다.
s = "Hello, World"
# Indexing (0-based, negative from end)
print(s[0]) # H
print(s[-1]) # d
print(s[7]) # W
# Slicing [start:stop:step]
print(s[0:5]) # Hello
print(s[7:]) # World
print(s[:5]) # Hello
print(s[::2]) # HloWrd (every 2nd char)
print(s[::-1]) # dlroW ,olleH (reverse!)
# Length
print(len(s)) # 12
# Slicing never raises IndexError
print(s[100:200]) # '' (empty string)분할 & 결합
split()은 문자열을 리스트로 나누고 join()은 리스트를 문자열로 결합합니다. 많은 문자열을 효율적으로 연결하려면 항상 join()을 사용하세요 — + 연산자는 중간 문자열을 생성합니다. partition()은 정확히 3부분(앞, 구분자, 뒤)으로 나눕니다.
# Split
csv = "a,b,c,d"
print(csv.split(",")) # ['a', 'b', 'c', 'd']
print(csv.split(",", 2)) # ['a', 'b', 'c,d'] (max 2 splits)
# Splitlines
text = "line1\nline2\nline3"
print(text.splitlines()) # ['line1', 'line2', 'line3']
# Partition (splits on first occurrence)
print("[email protected]".partition("@"))
# ('user', '@', 'domain.com')
# Join
words = ["Hello", "World"]
print(" ".join(words)) # Hello World
print("-".join(["2024", "01", "15"])) # 2024-01-15
print("".join(["a", "b", "c"])) # abc
# String concatenation
s = "Hello" + " " + "World"
parts = ["a"]
parts += "b" # NOT string concat - adds chars to list!제거 & 패딩
strip()은 기본적으로 선행/후행 공백을 제거하거나 지정된 문자를 제거합니다. zfill()은 선행 0으로 패딩합니다 (ID에 유용). rjust/ljust/center는 선택적 채우기 문자로 지정된 너비까지 패딩합니다.
# Strip whitespace (or specified chars)
s = " hello "
print(s.strip()) # "hello"
print(s.lstrip()) # "hello "
print(s.rstrip()) # " hello"
# Strip specific characters
print("xxxhelloxxx".strip("x")) # hello
# Padding / centering
print("42".zfill(5)) # 00042
print("hi".rjust(10)) # " hi"
print("hi".ljust(10, "-")) # "hi--------"
print("hi".center(10, "*")) # "****hi****"
# expandtabs
print("a\tb".expandtabs(4)) # "a b"Raw 문자열 & 이스케이프
Raw 문자열(r'...')은 백슬래시를 문자 그대로 처리합니다 — 정규식 패턴과 Windows 파일 경로에 필수적입니다. 삼중 따옴표 문자열은 줄바꿈을 유지합니다. 문자열은 반복을 위해 * 연산자를, 연결을 위해 +를 지원합니다.
# Escape sequences
print("Line1\nLine2") # newline
print("Tab\there") # tab
print("Quote: \"hi\"") # escaped quotes
print("Backslash: \\") # literal backslash
# Raw strings (ignore escapes) - great for regex
path = r"C:\Users\name\file.txt"
regex = r"\d{3}-\d{4}"
print(path) # C:\Users\name\file.txt
# Triple-quoted strings
multi = """
Multiple
lines
"""
# String multiplication
print("ab" * 3) # ababab숫자 & 수학
산술 연산자
Python에는 7개의 산술 연산자가 있습니다. /는 항상 float를 반환하고 //는 정수 나눗셈입니다 (음의 무한대를 향해 반올림). **는 거듭제곱입니다 (^가 아님 — 그것은 XOR입니다). % 연산자의 결과는 C/Java와 달리 제수의 부호를 따릅니다.
# Basic operators
print(7 + 3) # 10 addition
print(7 - 3) # 4 subtraction
print(7 * 3) # 21 multiplication
print(7 / 3) # 2.333... true division (always float)
print(7 // 3) # 2 floor division
print(7 % 3) # 1 modulo (remainder)
print(7 ** 3) # 343 exponentiation
# Floor division with negatives
print(-7 // 3) # -3 (rounds toward negative infinity)
print(-7 % 3) # 2 (result has same sign as divisor)
# Augmented assignment
x = 10
x += 5 # x = x + 5
x **= 2 # x = x ** 2Math 모듈
math 모듈은 수학 함수와 상수를 제공합니다. 모든 삼각 함수는 라디안을 사용합니다 — math.radians()/degrees()로 변환하세요. math.gcd()는 최대공약수를 찾습니다. 복소수에는 cmath 모듈을 사용하세요.
import math
# Constants
print(math.pi) # 3.141592653589793
print(math.e) # 2.718281828459045
print(math.inf) # inf
print(math.nan) # nan
# Functions
print(math.sqrt(16)) # 4.0
print(math.pow(2, 10)) # 1024.0
print(math.log(100, 10)) # 2.0 (log base 10)
print(math.log(math.e)) # 1.0 (natural log)
print(math.factorial(5)) # 120
print(math.gcd(12, 8)) # 4
# Rounding
print(math.floor(3.7)) # 3
print(math.ceil(3.2)) # 4
print(math.trunc(-3.7)) # -3 (toward zero)
# Trigonometry (radians)
print(math.sin(math.pi / 2)) # 1.0
print(math.degrees(math.pi)) # 180.0Random 모듈
random 모듈은 Mersenne Twister PRNG를 사용합니다 — 암호학적으로 안전하지 않습니다. 보안에는 secrets 모듈을 사용하세요. random.sample()은 고유한 항목을 선택하고 random.choices()는 중복을 허용합니다. 테스트에서 재현 가능한 결과를 위해 시드를 설정하세요.
import random
# Random integers
print(random.randint(1, 100)) # 1 to 100 inclusive
print(random.randrange(0, 10, 2)) # even number 0,2,4,6,8
# Random floats
print(random.random()) # 0.0 to 1.0
print(random.uniform(1.0, 10.0)) # random float in range
# Choice & sampling
colors = ["red", "green", "blue"]
print(random.choice(colors)) # one random item
print(random.sample(colors, 2)) # 2 unique items
print(random.choices(colors, k=5)) # 5 items (with replacement)
# Shuffle (in-place)
nums = [1, 2, 3, 4, 5]
random.shuffle(nums)
print(nums)
# Reproducible randomness
random.seed(42) # same seed = same sequenceDecimal & Fractions
float 정밀도 오류가 허용되지 않는 재무 계산에는 Decimal을 사용하세요 (예: 돈). 정확한 유리수 연산에는 Fraction을 사용하세요. 둘 다 float보다 느리지만 반올림 오류를 피합니다. 항상 float가 아닌 문자열에서 Decimal을 생성하세요.
from decimal import Decimal, getcontext
from fractions import Fraction
# Float precision issues
print(0.1 + 0.2) # 0.30000000000000004
# Decimal for exact decimal arithmetic
a = Decimal("0.1")
b = Decimal("0.2")
print(a + b) # 0.3 (exact!)
# Set precision
getcontext().prec = 6
print(Decimal(1) / Decimal(7)) # 0.142857
# Fractions for exact rational arithmetic
f1 = Fraction(1, 3)
f2 = Fraction(1, 6)
print(f1 + f2) # 1/2
print(float(f1)) # 0.3333...
# Fraction from string
print(Fraction("3/4")) # 3/4비트 연산자
비트 연산자는 정수의 개별 비트를 조작합니다. Python 정수는 임의 정밀도를 가지므로 시프트가 고정 너비 언어와 다르게 작동합니다. 일반적인 용도: 플래그, 마스크, 저수준 프로토콜 파싱. x & (x-1) == 0은 x가 2의 거듭제곱인지 확인합니다.
# Bitwise operators work on integers
a = 0b1010 # 10
b = 0b1100 # 12
print(a & b) # 8 (0b1000) AND
print(a | b) # 14 (0b1110) OR
print(a ^ b) # 6 (0b0110) XOR
print(~a) # -11 (NOT, two's complement)
print(a << 2) # 40 (left shift, multiply by 4)
print(a >> 1) # 5 (right shift, divide by 2)
# Binary representation
print(bin(10)) # 0b1010
print(hex(255)) # 0xff
print(oct(8)) # 0o10
print(int("1010", 2)) # 10 (parse binary)
# Common tricks
print(5 & 1) # 1 (check odd: nonzero = odd)
print(8 & (8-1)) # 0 (check power of 2)데이터 구조
리스트
리스트는 Python의 가장 다용도적인 데이터 구조입니다 — 순서가 있고, 가변적이며, 이질적입니다. append()는 O(1), insert(0, x)는 O(n)입니다. 양 끝에서의 빠른 작업에는 collections.deque를 사용하세요. sort()는 제자리에서 수행되고 sorted()는 새 리스트를 반환합니다.
# Lists are ordered, mutable sequences
nums = [1, 2, 3, 4, 5]
mixed = [1, "hello", True, 3.14]
# Adding elements
nums.append(6) # [1,2,3,4,5,6]
nums.insert(0, 0) # [0,1,2,3,4,5,6]
nums.extend([7, 8]) # extend with another list
# Removing elements
nums.remove(0) # remove by value
popped = nums.pop() # remove & return last
popped = nums.pop(0) # remove & return by index
del nums[0] # delete by index
nums.clear() # remove all
# Slicing (same as strings)
nums = [1, 2, 3, 4, 5]
print(nums[1:3]) # [2, 3]
print(nums[::-1]) # [5, 4, 3, 2, 1] reverse
# Sorting
nums.sort() # in-place sort
nums.sort(reverse=True) # descending
sorted_nums = sorted(nums) # returns new list튜플
튜플은 불변이고 리스트보다 빠릅니다. 고정 컬렉션, 여러 반환 값, 사전 키(리스트는 키가 될 수 없음)에 사용하세요. Named tuple은 가독성을 위해 필드 이름을 제공합니다. 단일 요소 튜플은 후행 쉼표가 필요합니다.
# Tuples are ordered, IMMUTABLE sequences
point = (3, 4)
single = (42,) # note the comma for single-element tuple
empty = ()
# Packing & unpacking
coordinates = 10, 20, 30 # packing
x, y, z = coordinates # unpacking
x, y = y, x # swap values!
# Multiple return values
def min_max(nums):
return min(nums), max(nums)
lo, hi = min_max([3, 1, 4, 1, 5])
# Named tuples (readable)
from collections import namedtuple
Point = namedtuple("Point", ["x", "y"])
p = Point(3, 4)
print(p.x, p.y) # 3 4
print(p[0], p[1]) # 3 4
# Tuples are immutable but can contain mutable objects
t = (1, [2, 3])
t[1].append(4) # OK: (1, [2, 3, 4])사전
사전은 해시 맵입니다 — 조회/삽입/삭제에 평균 O(1)입니다. 키는 해시 가능해야 합니다 (불변). Python 3.7부터 dict는 삽입 순서를 유지합니다. KeyError를 피하려면 get()을 사용하세요. dict comprehension은 dict를 우아하게 생성합니다.
# Dicts are key-value mappings (insertion-ordered since 3.7)
user = {"name": "Alice", "age": 30}
# Access
print(user["name"]) # Alice
print(user.get("email")) # None (no KeyError)
print(user.get("email", "N/A")) # N/A (default)
# Add/update
user["email"] = "[email protected]" # add
user["age"] = 31 # update
user.setdefault("role", "user") # set if missing
# Delete
del user["email"]
val = user.pop("age") # remove & return
# user.clear() # remove all
# Iteration
for key in user: # keys
print(key)
for k, v in user.items(): # key-value pairs
print(k, v)
for v in user.values(): # values
print(v)
# Dict comprehension
squares = {x: x**2 for x in range(5)}
# Merge dicts (3.9+)
merged = {"a": 1} | {"b": 2}집합
집합은 고유하고 해시 가능한 요소의 순서 없는 컬렉션입니다. 멤버십 테스트(리스트의 O(n)에 비해 O(1))와 집합 대수(합집합, 교집합, 차집합)에 뛰어납니다. frozenset은 불변이고 해시 가능합니다. 순서는 보장되지 않습니다.
# Sets are unordered collections of unique elements
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
# Set operations
print(a | b) # union: {1, 2, 3, 4, 5, 6}
print(a & b) # intersection: {3, 4}
print(a - b) # difference: {1, 2}
print(a ^ b) # symmetric difference: {1, 2, 5, 6}
# Methods
a.add(5) # add element
a.discard(10) # remove if present (no error)
a.remove(1) # remove (KeyError if missing)
a.update([6, 7]) # add multiple
# Membership test (O(1) - faster than list)
print(3 in a) # True
# Frozen set (immutable)
fs = frozenset([1, 2, 3])
# Common use: deduplicate
unique = list(set([1, 1, 2, 2, 3])) # [1, 2, 3]컴프리헨션
컴프리헨션은 간결하게 컬렉션을 생성하는 Pythonic 방법입니다. 제너레이터 표현식(대괄호 대신 괄호)은 지연 평가됩니다 — 요구에 따라 값을 생성하여 메모리를 절약합니다. 가독성을 위해 map()/filter()보다 컴프리헨션을 선호하세요.
# List comprehension
squares = [x**2 for x in range(10)]
evens = [x for x in range(20) if x % 2 == 0]
pairs = [(x, y) for x in range(3) for y in range(3)]
# Dict comprehension
square_map = {x: x**2 for x in range(5)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# Set comprehension
unique_lens = {len(w) for w in ["a", "ab", "abc", "ab"]}
# Generator expression (lazy, memory-efficient)
gen = (x**2 for x in range(1000000))
print(next(gen)) # 0
print(next(gen)) # 1
total = sum(x**2 for x in range(100)) # no extra list
# Nested comprehension (matrix)
matrix = [[i * 3 + j for j in range(3)] for i in range(3)]
# [[0,1,2], [3,4,5], [6,7,8]]Collections 모듈
collections 모듈은 특수 컨테이너를 제공합니다. Counter는 해시 가능한 항목을 셉니다. defaultdict는 누락된 키를 자동 생성합니다. deque는 양 끝에서 O(1) append/pop을 제공합니다 (리스트의 O(n)와 비교). 깨끗하고 효율적인 코드에 필수적입니다.
from collections import Counter, defaultdict, deque, OrderedDict
# Counter - counting
words = ["apple", "banana", "apple", "cherry", "banana", "apple"]
cnt = Counter(words)
print(cnt) # Counter({'apple': 3, 'banana': 2, 'cherry': 1})
print(cnt.most_common(2)) # [('apple', 3), ('banana', 2)]
# defaultdict - no KeyError
dd = defaultdict(list)
dd["fruits"].append("apple")
dd["fruits"].append("banana")
# dd["vegs"] automatically creates empty list
# deque - fast double-ended queue
dq = deque([1, 2, 3])
dq.appendleft(0) # [0, 1, 2, 3]
dq.append(4) # [0, 1, 2, 3, 4]
dq.popleft() # 0, deque is now [1, 2, 3, 4]
dq.rotate(1) # rotate right
# OrderedDict (less needed since 3.7, dicts are ordered)
od = OrderedDict([("a", 1), ("b", 2)])제어 흐름
If / Elif / Else
Python은 if/elif/else를 사용합니다 — 'elseif'가 아닌 'elif'에 주의하세요. 들여쓰기가 블록을 정의합니다. 삼항 'x if cond else y'는 표현식입니다. Python은 빈 컬렉션, 0, None, False를 거짓으로 취급합니다 — 간결한 조건문에 유용합니다.
score = 85
if score >= 90:
grade = "A"
elif score >= 80:
grade = "B"
elif score >= 70:
grade = "C"
else:
grade = "F"
print(f"Grade: {grade}") # Grade: B
# Conditional expression (ternary)
status = "pass" if score >= 60 else "fail"
# Truthy/falsy values
# Falsy: False, 0, 0.0, "", [], {}, (), None
# Everything else is truthy
if []: # False
print("never")
if [0]: # True (non-empty list)
print("always")For 루프 & 반복
Python의 for 루프는 반복 가능한 모든 항목을 반복합니다. range()는 숫자를 생성합니다 (배타적 stop). enumerate()는 항목과 인덱스를 짝지습니다. zip()은 여러 시퀀스를 병렬로 반복합니다. dict 키-값 쌍을 반복하려면 .items()를 사용하세요.
# range(start, stop, step)
for i in range(5): # 0, 1, 2, 3, 4
print(i)
for i in range(2, 10, 2): # 2, 4, 6, 8
print(i)
for i in range(10, 0, -1): # countdown
print(i)
# Iterate over collections
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit)
# enumerate for index + value
for idx, fruit in enumerate(fruits):
print(f"{idx}: {fruit}")
# zip to iterate multiple sequences
names = ["Alice", "Bob"]
ages = [30, 25]
for name, age in zip(names, ages):
print(f"{name}: {age}")
# Iterate dict
user = {"name": "Alice", "age": 30}
for key, value in user.items():
print(f"{key} = {value}")While 루프 & Break/Continue
while 루프는 조건이 참인 동안 반복합니다. break는 루프를 즉시 종료하고 continue는 다음 반복으로 건너뜁니다. for/else 구문은 루프가 break되지 않은 경우에만 else 블록을 실행합니다. pass는 빈 블록의 no-op 자리표시자입니다.
# Basic while
count = 0
while count < 5:
print(count)
count += 1
# break - exit loop
while True:
cmd = input("> ")
if cmd == "quit":
break
print(f"You said: {cmd}")
# continue - skip to next iteration
for i in range(10):
if i % 2 == 0:
continue # skip even numbers
print(i) # prints 1, 3, 5, 7, 9
# else clause (runs if no break)
for i in range(5):
if i == 10:
break
else:
print("Loop completed without break")
# pass - do nothing (placeholder)
for i in range(5):
pass # TODO: implementMatch 문 (Python 3.10+)
match 문(Python 3.10+)은 C의 switch를 훨씬 넘어서는 강력한 구조적 패턴 매칭입니다. 시퀀스, 매핑, 클래스 인스턴스를 매칭하고 변수를 바인딩할 수 있습니다. _ 패턴은 와일드카드(기본값)입니다. 'if'가 있는 가드는 조건을 추가합니다.
# Structural pattern matching (like switch)
def handle_command(cmd):
match cmd.split():
case ["quit"]:
return "Goodbye"
case ["hello", name]:
return f"Hello, {name}!"
case ["move", direction] if direction in "NSEW":
return f"Moving {direction}"
case ["add", x, y]:
return int(x) + int(y)
case _:
return "Unknown command"
print(handle_command("hello Alice")) # Hello, Alice!
# Matching data structures
match point:
case (0, 0):
print("origin")
case (0, y):
print(f"on y-axis at {y}")
case (x, 0):
print(f"on x-axis at {x}")
case (x, y):
print(f"at ({x}, {y})")이터레이터 & 제너레이터
제너레이터는 yield를 사용하여 지연 평가로 값을 생성합니다 — 모든 값을 미리 계산하지 않아 메모리를 절약합니다. 이터레이터 프로토콜(iter()와 next())을 구현합니다. 한 번 소진되면 끝입니다. 큰/무한 시퀀스, 파이프라인, 스트리밍 데이터에 제너레이터를 사용하세요.
# Iterator protocol
nums = [1, 2, 3]
it = iter(nums)
print(next(it)) # 1
print(next(it)) # 2
print(next(it)) # 3
# next(it) # StopIteration
# Generator function (uses yield)
def count_up_to(n):
count = 1
while count <= n:
yield count
count += 1
for num in count_up_to(5):
print(num) # 1, 2, 3, 4, 5
# Infinite generator
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
fib = fibonacci()
print(next(fib)) # 0
print(next(fib)) # 1
print(next(fib)) # 1
print(next(fib)) # 2
# Generator expression
squares = (x**2 for x in range(10))함수
함수 정의 & 호출
함수는 def로 정의됩니다. 기본 인수는 =를 사용합니다. Python은 명확성을 위해 키워드 인수를 지원합니다. 함수는 여러 값을 반환할 수 있습니다 (튜플로). docstring(삼중 따옴표)은 함수를 문서화하고 help()를 통해 접근할 수 있습니다.
# Basic function
def greet(name):
return f"Hello, {name}!"
print(greet("Alice")) # Hello, Alice!
# Default arguments
def greet(name, greeting="Hello"):
return f"{greeting}, {name}!"
print(greet("Bob")) # Hello, Bob!
print(greet("Bob", "Hi")) # Hi, Bob!
# Keyword arguments
print(greet(name="Carol", greeting="Hey"))
# Return multiple values (tuple)
def stats(nums):
return min(nums), max(nums), sum(nums) / len(nums)
lo, hi, avg = stats([1, 2, 3, 4, 5])
# Docstrings
def add(a, b):
"""Add two numbers and return the result.
Args:
a: First number
b: Second number
Returns:
Sum of a and b
"""
return a + b인수: *args & **kwargs
*args는 추가 위치 인수를 튜플로 수집하고 **kwargs는 추가 키워드 인수를 dict로 수집합니다. args/kwargs 이름은 규칙입니다. 함수 호출 시 *로 시퀀스를, **로 dict를 언팩할 수 있습니다. 순서: 위치, *args, 키워드, **kwargs.
# *args - variable positional arguments (tuple)
def sum_all(*args):
return sum(args)
print(sum_all(1, 2, 3)) # 6
print(sum_all(1, 2, 3, 4, 5)) # 15
# **kwargs - variable keyword arguments (dict)
def print_info(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
print_info(name="Alice", age=30, role="admin")
# Combining all
def func(a, b, *args, **kwargs):
print(f"a={a}, b={b}")
print(f"args={args}")
print(f"kwargs={kwargs}")
func(1, 2, 3, 4, x=5, y=6)
# a=1, b=2, args=(3, 4), kwargs={'x': 5, 'y': 6}
# Unpacking arguments
nums = [1, 2, 3]
print(sum_all(*nums)) # unpack list as args
opts = {"name": "Alice", "age": 30}
print_info(**opts) # unpack dict as kwargsLambda & 고계 함수
Lambda는 단일 표현식으로 제한됩니다 — 복잡한 로직에는 def를 사용하세요. sorted(), map(), filter()와 같은 고계 함수의 인수로 빛을 발합니다. 하지만 리스트 컴프리헨션이 map/filter보다 종종 더 읽기 쉽습니다. reduce()는 functools에 있습니다.
# Lambda - anonymous function (single expression)
square = lambda x: x ** 2
print(square(5)) # 25
# Common with sorted, map, filter, reduce
students = [("Alice", 85), ("Bob", 92), ("Carol", 78)]
# Sort by score (key function)
sorted_by_score = sorted(students, key=lambda s: s[1])
# [('Carol', 78), ('Alice', 85), ('Bob', 92)]
# map - apply function to each item
nums = [1, 2, 3, 4, 5]
doubled = list(map(lambda x: x * 2, nums))
# [2, 4, 6, 8, 10]
# filter - keep items where function returns True
evens = list(filter(lambda x: x % 2 == 0, nums))
# [2, 4]
# reduce - accumulate to single value
from functools import reduce
product = reduce(lambda a, b: a * b, nums)
# 120 (1*2*3*4*5)
# Prefer comprehensions over map/filter
doubled = [x * 2 for x in nums] # more Pythonic
evens = [x for x in nums if x % 2 == 0]데코레이터
데코레이터는 원래 코드를 수정하지 않고 동작을 추가하기 위해 함수를 감쌉니다. @구문은 syntactic sugar입니다. 인수가 있는 데코레이터는 추가 중첩 레벨이 필요합니다. 원래 함수의 메타데이터(이름, docstring)를 보존하려면 항상 functools.wraps를 사용하세요.
# A decorator modifies a function's behavior
def uppercase_result(func):
def wrapper(*args, **kwargs):
result = func(*args, **kwargs)
return result.upper()
return wrapper
@uppercase_result
def greet(name):
return f"hello, {name}"
print(greet("alice")) # HELLO, ALICE
# Decorator with arguments
def repeat(times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def say_hi():
print("Hi!")
say_hi() # prints "Hi!" three times
# Practical: timing decorator
import time
def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
print(f"{func.__name__} took {time.time() - start:.4f}s")
return result
return wrapper
# Use functools.wraps to preserve metadata
from functools import wraps
def my_decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
return func(*args, **kwargs)
return wrapper스코프 & 클로저
Python은 LEGB 스코프 순서로 이름을 해결합니다: Local, Enclosing, Global, Built-in. 함수 내에서 전역 변수를 재바인딩하려면 'global'을 사용하세요. 둘러싸는 스코프의 변수를 수정하려면 'nonlocal'(Python 3)을 사용하세요. 클로저는 둘러싸는 스코프를 기억합니다.
# LEGB rule: Local, Enclosing, Global, Built-in
x = "global"
def outer():
x = "enclosing"
def inner():
x = "local"
print(x) # local
inner()
print(x) # enclosing
outer()
print(x) # global
# global keyword - modify global variable
count = 0
def increment():
global count
count += 1
# nonlocal keyword - modify enclosing variable
def make_counter():
count = 0
def counter():
nonlocal count
count += 1
return count
return counter
c = make_counter()
print(c()) # 1
print(c()) # 2
print(c()) # 3