10분 만에 Python 배우기
Python은 간결한 문법과 강력한 기능으로 유명한 고급 인터프리터 프로그래밍 언어입니다. 이 튜토리얼은 최신 Python 3.13+ 버전을 기반으로 하여 Python을 빠르게 배울 수 있도록 도와줍니다.
1. 첫 번째 Python 프로그램 작성하기
간단한 프로그램으로 시작해봅시다. hello.py
라는 파일을 만들고 다음 코드를 입력하세요:
print("Hello, World!")
파일을 저장하고 터미널이나 명령줄에서 다음 명령을 실행하세요:
python hello.py
출력 결과는 다음과 같습니다:
Hello, World!
이 간단한 프로그램은 Python의 기본 출력 기능을 보여줍니다. print()
함수는 콘솔에 텍스트 정보를 표시하는 데 사용됩니다.
2. 기본 문법
Python의 문법은 간단하고 이해하기 쉽습니다. Python은 중괄호 {}
를 사용하는 다른 언어와 달리 들여쓰기를 사용하여 코드 블록을 정의합니다.
# 이것은 주석입니다
print("Hello, World!")
Python의 기본 문법 규칙:
- 들여쓰기: 기본적으로 4개의 공백을 사용하여 코드 블록의 수준을 나타냅니다. 예를 들어, 함수나 루프 내부의 코드는 들여쓰기를 해야 합니다.
- 주석: 한 줄 주석은
#
으로 시작하며, 여러 줄 주석은 삼중 따옴표"""
또는'''
를 사용합니다. - 문장: 일반적으로 한 줄에 하나의 문장이 있으며, 문장 끝에 세미콜론
;
은 필요하지 않습니다. - 코드 블록: 들여쓰기로 정의되며,
if
,for
, 또는 함수 본문 등이 이에 해당합니다.
다중 줄 주석 예제:
"""
이것은 여러 줄에 걸친
주석입니다.
"""
들여쓰기는 Python 문법의 핵심 기능으로, 코드 블록의 계층 구조를 정의하는 데 사용됩니다:
if True:
print("이 줄은 들여쓰기되었습니다")
print("이 줄도 들여쓰기되었습니다")
print("이 줄은 들여쓰기되지 않았습니다")
3. 변수와 데이터 타입
Python에서 변수는 데이터를 저장하는 컨테이너입니다. Python은 동적 타이핑 언어로, 변수의 타입을 미리 선언할 필요가 없습니다.
기본 변수 명명 규칙:
- 변수 이름은 문자, 숫자, 밑줄(_)만 포함할 수 있습니다.
- 변수 이름은 숫자로 시작할 수 없습니다.
- 변수 이름은 대소문자를 구분합니다.
- Python 키워드는 변수 이름으로 사용할 수 없습니다.
변수 타입은 할당된 값에 따라 결정됩니다. Python의 주요 기본 데이터 타입은 다음과 같습니다:
- 정수 (int): 예:
42
또는-10
, 크기 제한 없음. - 부동소수점 (float): 예:
3.14
또는2.5e3
(과학적 표기법). - 문자열 (str): 예:
"hello"
또는'world'
, 단일 또는 이중 따옴표 사용. - 불리언 (bool):
True
또는False
. - NoneType (None):
None
으로 표현되며, null 또는 값 없음을 나타냅니다.
Python은 코드 가독성을 높이기 위해 타입 힌트를 지원하며, 정적 검사와 IDE 지원에 사용되지만 런타임 동작에는 영향을 미치지 않습니다:
name: str = "Alice"
age: int = 25
3.1 숫자 타입 (Number)
Python은 정수 (int), 부동소수점 (float), 복소수 (complex) 세 가지 숫자 타입을 지원합니다.
# 정수
age = 25
population = 1000000
# 부동소수점
temperature = 36.5
pi = 3.14159
# 복소수
complex_num = 3 + 4j
3.2 문자열 (String)
문자열은 문자 시퀀스로, 단일 또는 이중 따옴표로 묶습니다.
single_quote = '단일 따옴표 문자열'
double_quote = "이중 따옴표 문자열"
multiline = """이것은
여러 줄 문자열입니다"""
문자열 연산:
text = "Python 프로그래밍"
print(len(text)) # 문자열 길이
print(text.upper()) # 대문자 변환
print(text.lower()) # 소문자 변환
print(text[0]) # 첫 번째 문자 접근
print(text[2:6]) # 문자열 슬라이싱
3.3 불리언 타입 (Boolean)
불리언 타입은 True
와 False
두 가지 값을 가집니다.
is_active = True
is_complete = False
# 불리언 연산
result1 = True and False # False
result2 = True or False # True
result3 = not True # False
3.4 None 타입 (None)
None
은 null 또는 값이 없는 상태를 나타냅니다.
value = None
if value is None:
print("값이 null입니다")
4. 데이터 구조
Python은 데이터를 저장하고 조작하기 위한 여러 내장 데이터 구조를 제공합니다. 아래는 자주 사용되는 데이터 구조와 사용법입니다.
4.1 리스트 (List)
리스트는 순서가 있고 변경 가능한 컬렉션입니다. 요소를 추가, 제거, 수정할 수 있습니다. 리스트는 대괄호 []
를 사용하여 정의됩니다.
numbers = [1, 2, 3, 4, 5]
numbers.append(6) # 요소 추가
numbers.insert(0, 0) # 특정 위치에 삽입
numbers.remove(3) # 특정 값 제거
numbers[0] = 10 # 요소 수정
print(numbers) # [10, 2, 4, 5, 6]
리스트 슬라이싱으로 하위 리스트 접근:
numbers = [10, 20, 30, 40, 50]
print(numbers[1:4]) # 출력: [20, 30, 40]
print(numbers[:3]) # 출력: [10, 20, 30]
print(numbers[-2:]) # 출력: [40, 50]
리스트 컴프리헨션:
squares = [x**2 for x in range(5)]
print(squares) # [0, 1, 4, 9, 16]
even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(even_squares) # [0, 4, 16, 36, 64]
4.2 튜플 (Tuple)
튜플은 순서가 있지만 변경 불가능한 컬렉션입니다. 생성 후 요소를 수정할 수 없습니다. 튜플은 괄호 ()
를 사용하여 정의됩니다. 변경 불가능성 덕분에 튜플은 일반적으로 리스트보다 빠르며, 딕셔너리 키로 사용할 수 있습니다.
point = (10, 20)
x, y = point # 언패킹
print(x, y) # 출력: 10 20
단일 요소 튜플은 쉼표가 필요합니다:
single_tuple = (42,)
4.3 딕셔너리 (Dict)
딕셔너리는 키-값 쌍의 순서 없는 (Python 3.7+에서는 순서 있음) 컬렉션입니다. 각 키는 고유하며 값과 연결됩니다. 딕셔너리는 중괄호 {}
를 사용하여 정의됩니다.
student = {
"name": "John",
"age": 20,
"major": "Computer Science"
}
# 딕셔너리 접근 및 수정
print(student["name"])
student["age"] = 21
student["gpa"] = 3.8
# 안전한 접근
print(student.get("phone", "제공되지 않음"))
# 딕셔너리 순회
for key, value in student.items():
print(f"{key}: {value}")
딕셔너리 컴프리헨션:
# 제곱 딕셔너리 생성
squares_dict = {x: x**2 for x in range(5)}
print(squares_dict) # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
# 조건부 딕셔너리 컴프리헨션
even_squares_dict = {x: x**2 for x in range(10) if x % 2 == 0}
print(even_squares_dict) # {0: 0, 2: 4, 4: 16, 6: 36, 8: 64}
4.4 세트 (Set)
세트는 중복 요소가 없는 순서 없는 컬렉션입니다. 중괄호 {}
또는 set()
을 사용하여 정의됩니다.
# 세트 생성
fruits = {"apple", "banana", "orange"}
numbers = set([1, 2, 3, 3, 4, 4, 5]) # 자동 중복 제거
print(numbers) # {1, 2, 3, 4, 5}
# 세트 연산
set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}
print(set1 | set2) # 합집합: {1, 2, 3, 4, 5, 6}
print(set1 & set2) # 교집합: {3, 4}
print(set1 - set2) # 차집합: {1, 2}
print(set1 ^ set2) # 대칭 차집합: {1, 2, 5, 6}
5. 연산자와 연산
Python은 다양한 연산과 비교를 위한 풍부한 연산자 세트를 제공하며, 산술, 비교, 논리, 비트, 식별 연산자를 포함합니다.
- 산술 연산자:
+
,-
,*
,/
,//
(정수 나누기),%
(나머지),**
(거듭제곱). - 비교 연산자:
==
,!=
,>
,<
,>=
,<=
. - 논리 연산자:
and
,or
,not
. - 멤버십 연산자:
in
,not in
. - 식별 연산자:
is
,is not
.
5.1 산술 연산자
산술 연산자는 수학 연산에 사용됩니다. 연산자 우선순위는 수학적 규칙을 따르며 (예: **
는 +
또는 -
보다 우선순위가 높음), 괄호 ()
를 사용하여 우선순위를 변경할 수 있습니다.
a, b = 10, 3
print(f"덧셈: {a + b}") # 13
print(f"뺄셈: {a - b}") # 7
print(f"곱셈: {a * b}") # 30
print(f"나눗셈: {a / b}") # 3.333...
print(f"정수 나눗셈: {a // b}") # 3
print(f"나머지: {a % b}") # 1
print(f"거듭제곱: {a ** b}") # 1000
5.2 비교 연산자
비교 연산자는 두 값을 비교하여 불리언 값(True
또는 False
)을 반환합니다.
x, y = 5, 10
print(f"같음: {x == y}") # False
print(f"다름: {x != y}") # True
print(f"초과: {x > y}") # False
print(f"미만: {x < y}") # True
print(f"이상: {x >= y}") # False
print(f"이하: {x <= y}") # True
5.3 논리 연산자
논리 연산자는 불리언 값(True
또는 False
)을 결합하거나 조작하며, 주로 조건문에서 사용됩니다.
a, b = True, False
print(f"AND 연산: {a and b}") # False
print(f"OR 연산: {a or b}") # True
print(f"NOT 연산: {not a}") # False
5.4 식별 연산자
is
연산자는 두 객체의 식별자를 비교하여 동일한 메모리 주소를 참조하는지 확인합니다(단순히 값이 같은지 비교하는 ==
와 다름).
list1 = [1, 2, 3]
list2 = [1, 2, 3]
list3 = list1
print(f"list1 is list2: {list1 is list2}") # False
print(f"list1 is list3: {list1 is list3}") # True
print(f"list1 == list2: {list1 == list2}") # True
5.5 멤버십 연산자
멤버십 연산자는 값이 시퀀스(예: 리스트, 튜플, 문자열, 세트)에 속해 있는지 테스트하여 불리언 값을 반환합니다.
fruits = ["apple", "banana", "orange"]
print(f"'apple' in fruits: {'apple' in fruits}") # True
print(f"'grape' not in fruits: {'grape' not in fruits}") # True
6. 제어 흐름
Python은 프로그램의 실행 순서를 관리하기 위한 여러 제어 흐름 문을 제공합니다.
6.1 if 문
if
문은 조건을 평가하여 조건이 True
일 때 해당 블록을 실행합니다. 복잡한 조건을 위해 elif
와 else
를 사용합니다.
age = 20
if age >= 18:
print("성인")
elif age >= 13:
print("청소년")
else:
print("어린이")
6.2 for 루프
for
루프는 이터러블 객체(예: 리스트, 튜플, 문자열, range)를 순회합니다.
# 리스트 순회
fruits = ["apple", "banana", "cherry"]
for fruit in fruits:
print(fruit)
# range()를 사용한 루프
for i in range(5):
print(i) # 출력: 0, 1, 2, 3, 4
6.3 while 루프
while
루프는 조건이 True
인 동안 블록을 계속 실행합니다.
count = 0
while count < 5:
print(count)
count += 1
- break와 continue:
break
는 루프를 종료하고,continue
는 현재 반복을 건너뜁니다.
for i in range(10):
if i == 5:
break
if i % 2 == 0:
continue
print(i) # 출력: 1, 3
6.4 match 문
Python 3.10에서 도입된 match
문은 강력한 구조적 패턴 매칭을 제공하며, if/elif/else
체인을 대체하는 고급 대안입니다.
http_status = 200
match http_status:
case 200 | 201:
print("성공")
case 404:
print("찾을 수 없음")
case 500:
print("서버 오류")
case _: # 와일드카드, 다른 모든 경우와 매칭
print("알 수 없는 상태")
7. 입력과 출력
7.1 기본 입력과 출력
사용자 입력을 받기 위해 input()
함수를, 정보를 출력하기 위해 print()
함수를 사용합니다.
# 사용자 입력 받기
name = input("이름을 입력하세요: ")
age = int(input("나이를 입력하세요: "))
# 정보 출력
print("환영합니다", name)
print("당신은", age, "세입니다")
7.2 포맷팅된 출력 (f-strings)
Python 3.6+에서 도입된 f-문자열(포맷팅된 문자열 리터럴)은 문자열을 포맷팅하는 편리하고 강력한 방법입니다. 문자열 앞에 f
또는 F
를 붙이고 중괄호 {}
안에 변수나 표현식을 삽입합니다.
user = "Alice"
items = 3
total_cost = 45.5
# f-문자열로 포맷팅된 메시지
message = f"사용자 {user}가 {items}개 아이템을 ${total_cost:.2f}에 구매했습니다."
print(message)
# f-문자열에서 표현식
print(f"2 + 3은 {2 + 3}입니다")
f-문자열에서 표현식과 함수 호출:
width = 10
height = 5
# f-문자열에서 표현식 사용
area = f"직사각형 면적: {width * height}"
print(area)
# 함수 호출
text = "python"
formatted = f"대문자: {text.upper()}, 길이: {len(text)}"
print(formatted)
f-문자열에서 포맷팅 옵션:
pi = 3.14159265359
large_number = 1234567
# 숫자 포맷팅
print(f"Pi (소수점 2자리): {pi:.2f}")
print(f"Pi (소수점 4자리): {pi:.4f}")
print(f"큰 숫자 (천 단위): {large_number:,}")
print(f"백분율: {0.85:.1%}")
# 문자열 정렬
name = "Python"
print(f"왼쪽 정렬: '{name:<10}'")
print(f"오른쪽 정렬: '{name:>10}'")
print(f"가운데 정렬: '{name:^10}'")
날짜와 시간 포맷팅:
from datetime import datetime
now = datetime.now()
print(f"현재 시간: {now}")
print(f"포맷팅된 시간: {now:%Y-%m-%d %H:%M:%S}")
print(f"날짜만: {now:%Y-%m-%d}")
9. 함수
Python의 함수는 특정 작업을 위한 재사용 가능한 코드 블록으로, def
키워드를 사용하여 정의하며, 기본 매개변수, 가변 인수, 키워드 인수를 지원합니다.
기본 함수 정의:
def greet(name):
"""인사 함수"""
return f"안녕하세요, {name}!"
# 함수 호출
message = greet("John")
print(message)
키워드 인수:
키워드 인수는 parameter_name=value
구문을 사용하여 전달됩니다.
def greet(name, greeting="안녕"):
return f"{greeting}, {name}!"
print(greet("Alice")) # 출력: 안녕, Alice!
print(greet("Bob", "안녕하세요")) # 출력: 안녕하세요, Bob!
가변 인수:
가변 인수는 함수가 임의의 수의 인수를 받아들이도록 허용하며, 위치 인수(*args
) 또는 키워드 인수(**kwargs
)를 사용합니다.
# 위치 가변 인수 (*args)
def sum_numbers(*args):
return sum(args)
print(sum_numbers(1, 2, 3, 4)) # 출력: 10
# 키워드 가변 인수 (**kwargs)
def print_kwargs(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
print_kwargs(name="Alice", age=25, city="서울")
함수 주석:
함수 주석은 함수 매개변수와 반환값에 설명적인 메타데이터를 추가하여 가독성과 문서화를 개선합니다.
def calculate_area(length: float, width: float) -> float:
"""직사각형 면적 계산"""
return length * width
def process_user(name: str, age: int, active: bool = True) -> dict:
"""사용자 정보 처리"""
return {
"name": name,
"age": age,
"active": active
}
10. 람다 표현식
람다 표현식은 익명 함수를 생성하여 작은 함수를 간결하게 정의합니다.
square = lambda x: x ** 2
print(square(5)) # 출력: 25
map
또는 filter
와 같은 고차 함수와 자주 사용됩니다:
numbers = [1, 2, 3, 4]
squares = list(map(lambda x: x ** 2, numbers))
print(squares) # 출력: [1, 4, 9, 16]
11. 클래스와 객체
Python은 class
키워드를 사용하여 객체지향 프로그래밍을 지원합니다:
class Person:
"""사람 클래스"""
def __init__(self, name, age):
"""생성자"""
self.name = name
self.age = age
def introduce(self):
"""소개 메서드"""
return f"저는 {self.name}이고, {self.age}세입니다"
def have_birthday(self):
"""생일 메서드"""
self.age += 1
return f"{self.name}이(가) 생일을 맞아 이제 {self.age}세입니다"
# 객체 생성
person1 = Person("John", 25)
person2 = Person("Jane", 30)
print(person1.introduce())
print(person2.have_birthday())
11.1 클래스와 인스턴스 속성
Python에서 클래스 속성과 인스턴스 속성은 클래스와 객체에 데이터를 저장하는 두 가지 속성 유형입니다.
- 클래스 속성: 메서드 외부에서 정의되며, 클래스 자체에 속하며 모든 인스턴스에서 공유됩니다.
- 인스턴스 속성: 메서드(보통
__init__
)에서 정의되며,self
를 통해 특정 인스턴스에 바인딩됩니다.
class Student:
# 클래스 속성
school = "Stanford University"
student_count = 0
def __init__(self, name, major):
# 인스턴스 속성
self.name = name
self.major = major
Student.student_count += 1
@classmethod
def get_student_count(cls):
"""클래스 메서드"""
return cls.student_count
@staticmethod
def is_valid_age(age):
"""정적 메서드"""
return 0 < age < 150
# 사용 예제
student1 = Student("John", "Computer Science")
student2 = Student("Jane", "Mathematics")
print(f"학교: {Student.school}")
print(f"총 학생 수: {Student.get_student_count()}")
print(f"유효한 나이: {Student.is_valid_age(20)}")
11.2 클래스 상속
상속은 클래스(하위 클래스)가 다른 클래스(상위 클래스)의 속성과 메서드를 상속받아 코드 재사용과 확장을 가능하게 합니다.
class Animal:
def __init__(self, name, species):
self.name = name
self.species = species
def make_sound(self):
return f"{self.name}이(가) 소리를 냅니다"
def info(self):
return f"{self.name}은(는) {self.species}입니다"
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name, "Dog")
self.breed = breed
def make_sound(self):
return f"{self.name}이(가) 짖습니다"
def fetch(self):
return f"{self.name}이(가) 공을 가져옵니다"
class Cat(Animal):
def __init__(self, name, color):
super().__init__(name, "Cat")
self.color = color
def make_sound(self):
return f"{self.name}이(가) 야옹합니다"
def climb(self):
return f"{self.name}이(가) 나무를 올라갑니다"
# 상속 사용
dog = Dog("Buddy", "Golden Retriever")
cat = Cat("Mimi", "Orange")
print(dog.info())
print(dog.make_sound())
print(dog.fetch())
print(cat.info())
print(cat.make_sound())
print(cat.climb())
11.3 특수 메서드 (매직 메서드)
특수 메서드(또는 매직 메서드)는 특정 시나리오에서 Python이 자동으로 호출하는 이중 밑줄 메서드로, 특정 동작을 정의합니다.
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def __str__(self):
"""문자열 표현"""
return f"직사각형({self.width}x{self.height})"
def __repr__(self):
"""공식 문자열 표현"""
return f"Rectangle(width={self.width}, height={self.height})"
def __eq__(self, other):
"""동등 비교"""
if isinstance(other, Rectangle):
return self.width == other.width and self.height == other.height
return False
def __lt__(self, other):
"""미만 비교 (면적으로)"""
if isinstance(other, Rectangle):
return self.area() < other.area()
return NotImplemented
def __add__(self, other):
"""덧셈 연산"""
if isinstance(other, Rectangle):
return Rectangle(self.width + other.width, self.height + other.height)
return NotImplemented
def area(self):
"""면적 계산"""
return self.width * self.height
# 특수 메서드 사용
rect1 = Rectangle(3, 4)
rect2 = Rectangle(5, 6)
rect3 = Rectangle(3, 4)
print(rect1) # 직사각형(3x4)
print(repr(rect1)) # Rectangle(width=3, height=4)
print(rect1 == rect3) # True
print(rect1 < rect2) # True
print(rect1 + rect2) # 직사각형(8x10)
12. 컨텍스트 매니저
컨텍스트 매니저는 리소스 획득과 해제를 보장하며, 주로 with
문과 함께 파일이나 데이터베이스 연결과 같은 리소스 관리에 사용됩니다.
12.1 컨텍스트 매니저 사용
파일 작업은 컨텍스트 매니저의 일반적인 사용 사례입니다:
with open("example.txt", "r") as file:
content = file.read()
print(content)
with
문은 작업 후 파일이 자동으로 닫히도록 보장합니다.
12.2 사용자 정의 컨텍스트 매니저
__enter__
와 __exit__
메서드를 정의하여 사용자 정의 컨텍스트 매니저를 생성합니다:
class DatabaseConnection:
def __init__(self, database_name):
self.database_name = database_name
self.connection = None
def __enter__(self):
"""컨텍스트 진입 시 호출"""
print(f"데이터베이스에 연결 중: {self.database_name}")
self.connection = f"{self.database_name}에 연결"
return self.connection
def __exit__(self, exc_type, exc_value, traceback):
"""컨텍스트 종료 시 호출"""
print(f"데이터베이스 연결 종료: {self.database_name}")
if exc_type:
print(f"예외 발생: {exc_type.__name__}: {exc_value}")
self.connection = None
return False # 예외를 억제하지 않음
# 사용자 정의 컨텍스트 매니저 사용
with DatabaseConnection("user_database") as conn:
print(f"연결 사용 중: {conn}")
print("데이터베이스 작업 수행 중...")
contextlib
모듈을 사용하여 컨텍스트 매니저 생성:
from contextlib import contextmanager
import time
@contextmanager
def timer(operation_name):
"""타이머 컨텍스트 매니저"""
print(f"{operation_name} 시작")
start_time = time.time()
try:
yield
finally:
end_time = time.time()
print(f"{operation_name}이(가) {end_time - start_time:.2f}초 만에 완료되었습니다")
# 데코레이터 기반 컨텍스트 매니저 사용
with timer("데이터 처리"):
# 시간 소모적인 작업 시뮬레이션
time.sleep(1)
print("데이터 처리 중...")
13. 예외 처리
예외 처리는 프로그램의 견고성을 보장하며, try
, except
, else
, finally
를 사용하여 예외를 관리합니다.
try:
result = 10 / 0
except ZeroDivisionError:
print("0으로 나눌 수 없습니다!")
else:
print("나눗셈 성공")
finally:
print("항상 실행됩니다")
출력:
0으로 나눌 수 없습니다!
항상 실행됩니다
14. 파일 작업
Python은 컨텍스트 매니저와 함께 파일 읽기 및 쓰기를 위한 간단한 메서드를 제공합니다.
14.1 파일 읽기
텍스트 파일 내용 읽기:
with open("example.txt", "r") as file:
content = file.read()
print(content)
한 줄씩 읽기:
with open("example.txt", "r") as file:
for line in file:
print(line.strip())
14.2 파일 쓰기
텍스트 파일에 쓰기:
with open("output.txt", "w") as file:
file.write("안녕하세요, Python!\n")
내용 추가:
with open("output.txt", "a") as file:
file.write("새로운 내용 추가.\n")
15. 모듈과 패키지
모듈은 Python 코드를 포함하는 파일이고, 패키지는 여러 모듈을 포함하는 디렉토리입니다. import
를 사용하여 모듈을 가져옵니다:
import math
print(math.sqrt(16)) # 출력: 4.0
사용자 정의 모듈 예제 (파일 이름이 mymodule.py
라고 가정):
# mymodule.py
def say_hello():
return "모듈에서 안녕하세요!"
가져오고 사용:
import mymodule
print(mymodule.say_hello()) # 출력: 모듈에서 안녕하세요!
16. 스코프와 네임스페이스
16.1 스코프
스코프는 변수가 접근 가능한 영역을 정의합니다. Python은 변수 조회를 위해 LEGB 규칙을 따릅니다:
- L (Local): 함수 또는 클래스 메서드 내부.
- E (Enclosing): 중첩 함수의 외부 함수(클로저).
- G (Global): 모듈 수준.
- B (Built-in):
print()
또는len()
과 같은 내장 함수 및 예외.
x = "전역 x"
def outer_func():
x = "포괄 x"
def inner_func():
x = "로컬 x"
print(x) # 로컬 스코프 x 접근
inner_func()
print(x) # 포괄 스코프 x 접근
outer_func()
print(x) # 전역 스코프 x 접근
global
또는 nonlocal
을 사용하여 스코프 변수 수정:
x = "전역"
def modify_global():
global x
x = "수정됨"
modify_global()
print(x) # 출력: 수정됨
16.2 네임스페이스
네임스페이스는 이름에서 객체로의 매핑으로, 변수 이름이 키이고 객체가 값인 딕셔너리와 같습니다.
각 모듈, 함수, 클래스는 고유한 네임스페이스를 가지며, 이름 충돌을 방지합니다. globals()
와 locals()
를 사용하여 네임스페이스를 검사할 수 있습니다.
a_variable = 10
def some_function():
b_variable = 20
# locals()는 현재 로컬 네임스페이스 딕셔너리를 반환
print(f"로컬: {locals()}")
print(f"글로벌: {globals().keys()}") # 글로벌 네임스페이스의 키 출력
some_function()
17. 제너레이터
제너레이터는 값을 한 번에 모두 생성하지 않고 필요할 때 생성하는 특수 이터레이터로, 대량 데이터셋에 메모리 효율적입니다.
제너레이터는 yield
키워드를 사용하여 값을 느리게 반환합니다:
def fibonacci(n):
a, b = 0, 1
for _ in range(n):
yield a
a, b = b, a + b
for num in fibonacci(5):
print(num) # 출력: 0, 1, 1, 2, 3
18. 멀티스레딩
멀티스레딩은 프로그램이 여러 작업을 동시에 수행하도록 하며, 네트워크 요청이나 파일 작업과 같은 I/O 바운드 작업에 유용합니다.
Python의 threading
모듈은 스레드 생성 및 관리를 위한 도구를 제공합니다. 전역 인터프리터 락(GIL)으로 인해 단일 프로세스에서 진정한 CPU 병렬 처리는 불가능하지만, I/O 바운드 작업의 성능은 크게 향상됩니다.
import threading
import time
def worker(thread_name):
print(f"스레드 {thread_name} 시작...")
time.sleep(2) # 시간 소모적인 작업 시뮬레이션
print(f"스레드 {thread_name} 종료.")
# 스레드 생성
thread1 = threading.Thread(target=worker, args=("A",))
thread2 = threading.Thread(target=worker, args=("B",))
# 스레드 시작
thread1.start()
thread2.start()
# 모든 스레드가 완료될 때까지 대기
thread1.join()
thread2.join()
print("모든 스레드 완료.")
19. 비동기 프로그래밍
비동기 프로그래밍은 높은 I/O, 높은 동시성 시나리오에 이상적이며, 스레드 대신 이벤트 루프를 사용하여 작업을 관리합니다.
Python은 asyncio
라이브러리와 async/await
구문을 통해 비동기 프로그래밍을 지원합니다.
async def
: 코루틴을 정의합니다.await
: 코루틴 실행을 일시 중지하고, 대기 가능한 객체가 완료될 때까지 기다립니다.
import asyncio
async def say_hello():
print("안녕")
await asyncio.sleep(1) # 비차단 sleep, I/O 시뮬레이션
print("세계")
async def main():
# 태스크 생성 및 대기
await asyncio.create_task(say_hello())
# 메인 코루틴 실행
asyncio.run(main())
출력:
안녕
세계