Python 기초 문법 (1‐3장): 변수, 조건문, 함수 - glasslego/getting-started-with-python GitHub Wiki

1. 변수와 자료형

1.1 변수 선언과 할당

# 변수 선언 (타입 지정 없이)
name = "Alice"
age = 25
height = 165.5
is_student = True

# 다중 할당
x, y, z = 1, 2, 3
a = b = c = 10

# 변수명 규칙
valid_name = "good"      # 문자, 숫자, _ 사용 가능
_private = "private"     # _로 시작 가능
number123 = "good"       # 숫자 포함 가능
# 2invalid = "bad"       # 숫자로 시작 불가
# my-var = "bad"         # - 사용 불가

1.2 기본 자료형

1.2.1 숫자형 (Numbers)

# 정수 (int)
integer_num = 42
big_integer = 1234567890123456789  # 임의 크기 지원

# 실수 (float)
float_num = 3.14
scientific = 1.23e-4  # 과학적 표기법

# 복소수 (complex)
complex_num = 3 + 4j

# 진법 표현
binary = 0b1010      # 2진법 (10)
octal = 0o12         # 8진법 (10)
hexadecimal = 0xa    # 16진법 (10)

# 타입 확인
print(type(integer_num))  # <class 'int'>
print(isinstance(float_num, float))  # True

1.2.2 문자열 (String)

# 문자열 생성
single_quote = 'Hello'
double_quote = "World"
triple_quote = """여러 줄
문자열
가능"""

# 문자열 연산
greeting = "Hello" + " " + "World"  # 연결
repeat = "Ha" * 3                   # 반복: "HaHaHa"

# 문자열 인덱싱과 슬라이싱
text = "Python"
print(text[0])     # 'P' (첫 번째 문자)
print(text[-1])    # 'n' (마지막 문자)
print(text[0:3])   # 'Pyt' (0부터 2까지)
print(text[2:])    # 'thon' (2부터 끝까지)
print(text[:4])    # 'Pyth' (처음부터 3까지)
print(text[::2])   # 'Pto' (2칸씩 건너뛰기)

# 문자열 메서드
name = "  Alice Bob  "
print(name.strip())           # "Alice Bob" (공백 제거)
print(name.upper())           # "  ALICE BOB  "
print(name.lower())           # "  alice bob  "
print(name.replace("Alice", "Charlie"))  # "  Charlie Bob  "
print(name.split())           # ['Alice', 'Bob']
print("o" in "Hello")         # True (포함 여부)

# 문자열 포매팅
name = "Alice"
age = 25

# 1) % 포매팅 (구식)
print("이름: %s, 나이: %d" % (name, age))

# 2) .format() 메서드
print("이름: {}, 나이: {}".format(name, age))
print("이름: {name}, 나이: {age}".format(name=name, age=age))

# 3) f-string (Python 3.6+, 추천)
print(f"이름: {name}, 나이: {age}")
print(f"계산: {2 + 3}")

1.2.3 불린형 (Boolean)

# 불린값
is_true = True
is_false = False

# 불린 연산
print(True and False)  # False
print(True or False)   # True
print(not True)        # False

# 다른 타입의 불린 변환
print(bool(1))         # True
print(bool(0))         # False
print(bool(""))        # False (빈 문자열)
print(bool("hello"))   # True
print(bool([]))        # False (빈 리스트)
print(bool([1, 2]))    # True

1.3 컬렉션 자료형

1.3.1 리스트 (List)

# 리스트 생성
numbers = [1, 2, 3, 4, 5]
mixed = [1, "hello", 3.14, True]
empty_list = []
nested = [1, 2], [3, 4], [5, 6](/glasslego/getting-started-with-python/wiki/1,-2],-[3,-4],-[5,-6)

# 리스트 인덱싱과 슬라이싱
print(numbers[0])      # 1
print(numbers[-1])     # 5
print(numbers[1:4])    # [2, 3, 4]

# 리스트 메서드
fruits = ["apple", "banana"]
fruits.append("orange")           # 끝에 추가
fruits.insert(1, "grape")         # 특정 위치에 삽입
fruits.remove("banana")           # 값으로 제거
popped = fruits.pop()             # 마지막 요소 제거 후 반환
fruits.extend(["kiwi", "mango"])  # 여러 요소 추가

print(fruits)  # ['apple', 'grape', 'orange', 'kiwi', 'mango']
print(len(fruits))      # 길이
print(fruits.count("apple"))  # 개수 세기
print(fruits.index("grape"))  # 인덱스 찾기

# 리스트 정렬
numbers = [3, 1, 4, 1, 5]
numbers.sort()          # 원본 수정
print(numbers)          # [1, 1, 3, 4, 5]

numbers = [3, 1, 4, 1, 5]
sorted_nums = sorted(numbers)  # 새 리스트 반환
print(sorted_nums)      # [1, 1, 3, 4, 5]
print(numbers)          # [3, 1, 4, 1, 5] (원본 유지)

# 리스트 컴프리헨션
squares = [x**2 for x in range(5)]          # [0, 1, 4, 9, 16]
evens = [x for x in range(10) if x % 2 == 0]  # [0, 2, 4, 6, 8]

1.3.2 튜플 (Tuple)

# 튜플 생성 (불변)
coordinates = (10, 20)
single_tuple = (42,)  # 단일 요소 튜플은 쉼표 필요
empty_tuple = ()

# 튜플 언패킹
x, y = coordinates
print(f"x: {x}, y: {y}")  # x: 10, y: 20

# 튜플은 수정 불가
# coordinates[0] = 30  # TypeError 발생

# 튜플 메서드
numbers = (1, 2, 3, 2, 4, 2)
print(numbers.count(2))   # 3
print(numbers.index(3))   # 2

1.3.3 딕셔너리 (Dictionary)

# 딕셔너리 생성
person = {
    "name": "Alice",
    "age": 25,
    "city": "Seoul"
}

# 빈 딕셔너리
empty_dict = {}
# 또는
empty_dict = dict()

# 딕셔너리 접근과 수정
print(person["name"])        # "Alice"
print(person.get("age"))     # 25
print(person.get("height", "Unknown"))  # "Unknown" (기본값)

person["age"] = 26           # 수정
person["height"] = 165       # 추가
del person["city"]           # 삭제

# 딕셔너리 메서드
print(person.keys())         # dict_keys(['name', 'age', 'height'])
print(person.values())       # dict_values(['Alice', 26, 165])
print(person.items())        # dict_items([('name', 'Alice'), ('age', 26), ('height', 165)])

# 딕셔너리 순회
for key in person:
    print(f"{key}: {person[key]}")

for key, value in person.items():
    print(f"{key}: {value}")

# 딕셔너리 컴프리헨션
squares = {x: x**2 for x in range(5)}  # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

1.3.4 집합 (Set)

# 집합 생성 (중복 제거, 순서 없음)
numbers = {1, 2, 3, 4, 5}
unique_chars = set("hello")  # {'h', 'e', 'l', 'o'}

# 집합 연산
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}

# 집합 메서드
fruits = {"apple", "banana"}
fruits.add("orange")         # 요소 추가
fruits.update(["grape", "kiwi"])  # 여러 요소 추가
fruits.remove("banana")      # 요소 제거 (없으면 에러)
fruits.discard("mango")      # 요소 제거 (없어도 에러 없음)

print("apple" in fruits)     # True (포함 여부)

1.4 타입 변환

# 명시적 타입 변환
str_num = "123"
int_num = int(str_num)       # 123
float_num = float(str_num)   # 123.0

num = 42
str_from_num = str(num)      # "42"

# 리스트, 튜플, 집합 간 변환
list_data = [1, 2, 3, 2]
tuple_data = tuple(list_data)    # (1, 2, 3, 2)
set_data = set(list_data)        # {1, 2, 3}
back_to_list = list(set_data)    # [1, 2, 3]

# 문자열을 리스트로
chars = list("hello")            # ['h', 'e', 'l', 'l', 'o']
words = "apple,banana,orange".split(",")  # ['apple', 'banana', 'orange']

2. 조건문과 반복문

2.1 조건문 (if, elif, else)

2.1.1 기본 if문

age = 18

if age >= 18:
    print("성인입니다.")
else:
    print("미성년자입니다.")

# 다중 조건
score = 85

if score >= 90:
    grade = "A"
elif score >= 80:
    grade = "B"
elif score >= 70:
    grade = "C"
else:
    grade = "F"

print(f"점수: {score}, 등급: {grade}")

2.1.2 비교 연산자

x = 10
y = 20

print(x == y)    # False (같음)
print(x != y)    # True (다름)
print(x < y)     # True (작음)
print(x <= y)    # True (작거나 같음)
print(x > y)     # False (큼)
print(x >= y)    # False (크거나 같음)

# 체인 비교
age = 25
print(18 <= age <= 65)  # True

2.1.3 논리 연산자

age = 25
has_license = True

# and: 둘 다 True여야 True
if age >= 18 and has_license:
    print("운전 가능")

# or: 하나라도 True면 True
weekend = True
holiday = False
if weekend or holiday:
    print("쉬는 날")

# not: 반대
is_working = False
if not is_working:
    print("일하지 않는 중")

2.1.4 멤버십 연산자

fruits = ["apple", "banana", "orange"]

if "apple" in fruits:
    print("사과가 있습니다.")

if "grape" not in fruits:
    print("포도가 없습니다.")

# 문자열에서도 사용 가능
text = "Python Programming"
if "Python" in text:
    print("Python이 포함되어 있습니다.")

2.1.5 삼항 연산자 (조건부 표현식)

age = 20
status = "성인" if age >= 18 else "미성년자"
print(status)  # "성인"

# 함수 호출에서도 사용
def get_abs(x):
    return x if x >= 0 else -x

print(get_abs(-5))  # 5

2.2 반복문

2.2.1 for 루프

# 리스트 반복
fruits = ["apple", "banana", "orange"]
for fruit in fruits:
    print(f"과일: {fruit}")

# range() 함수 사용
for i in range(5):          # 0, 1, 2, 3, 4
    print(i)

for i in range(1, 6):       # 1, 2, 3, 4, 5
    print(i)

for i in range(0, 10, 2):   # 0, 2, 4, 6, 8
    print(i)

# enumerate() 사용 (인덱스와 값)
for index, fruit in enumerate(fruits):
    print(f"{index}: {fruit}")

# 딕셔너리 반복
person = {"name": "Alice", "age": 25, "city": "Seoul"}

for key in person:
    print(f"{key}: {person[key]}")

for key, value in person.items():
    print(f"{key}: {value}")

# zip() 함수 (여러 리스트 동시 반복)
names = ["Alice", "Bob", "Charlie"]
ages = [25, 30, 35]

for name, age in zip(names, ages):
    print(f"{name}: {age}세")

2.2.2 while 루프

# 기본 while문
count = 0
while count < 5:
    print(f"카운트: {count}")
    count += 1

# 무한 루프 (조건부 탈출)
while True:
    user_input = input("종료하려면 'quit' 입력: ")
    if user_input == "quit":
        break
    print(f"입력값: {user_input}")

# while-else
num = 5
while num > 0:
    print(num)
    num -= 1
else:
    print("카운트다운 완료!")  # break로 나가지 않으면 실행

2.2.3 반복문 제어 (break, continue)

# break: 루프 완전히 종료
for i in range(10):
    if i == 5:
        break
    print(i)  # 0, 1, 2, 3, 4

# continue: 현재 반복만 건너뛰고 다음 반복 계속
for i in range(10):
    if i % 2 == 0:  # 짝수면 건너뛰기
        continue
    print(i)  # 1, 3, 5, 7, 9

# 중첩 루프에서 break
for i in range(3):
    for j in range(3):
        if j == 1:
            break  # 안쪽 루프만 종료
        print(f"i: {i}, j: {j}")

2.2.4 리스트 컴프리헨션 (고급)

# 기본 형태
numbers = [1, 2, 3, 4, 5]
squares = [x**2 for x in numbers]
print(squares)  # [1, 4, 9, 16, 25]

# 조건부 컴프리헨션
evens = [x for x in range(10) if x % 2 == 0]
print(evens)  # [0, 2, 4, 6, 8]

# 중첩 루프
matrix = [[i*j for j in range(3)] for i in range(3)]
print(matrix)  # [0, 0, 0], [0, 1, 2], [0, 2, 4](/glasslego/getting-started-with-python/wiki/0,-0,-0],-[0,-1,-2],-[0,-2,-4)

# for문 2개로 동일하게 작성
matrix = []
for i in range(3):      # 외부 for문 (행)
    row = []            # 각 행을 위한 빈 리스트
    for j in range(3):  # 내부 for문 (열)
        row.append(i*j) # i*j 값을 행에 추가
    matrix.append(row)  # 완성된 행을 matrix에 추가

# 딕셔너리 컴프리헨션
word_lengths = {word: len(word) for word in ["apple", "banana", "orange"]}
print(word_lengths)  # {'apple': 5, 'banana': 6, 'orange': 6}

# 집합 컴프리헨션
unique_lengths = {len(word) for word in ["apple", "banana", "orange", "grape"]}
print(unique_lengths)  # {5, 6}

3. 함수

3.1 함수 정의와 호출

3.1.1 기본 함수

# 기본 함수 정의
def greet():
    print("안녕하세요!")

# 함수 호출
greet()  # "안녕하세요!"

# 매개변수가 있는 함수
def greet_person(name):
    print(f"안녕하세요, {name}님!")

greet_person("Alice")  # "안녕하세요, Alice님!"

# 반환값이 있는 함수
def add(a, b):
    return a + b

result = add(3, 5)
print(result)  # 8

3.1.2 매개변수와 인수

기본 매개변수
def greet(name, greeting="안녕하세요"):
    return f"{greeting}, {name}님!"

print(greet("Alice"))              # "안녕하세요, Alice님!"
print(greet("Bob", "반갑습니다"))   # "반갑습니다, Bob님!"
키워드 인수
def introduce(name, age, city="서울"):
    return f"이름: {name}, 나이: {age}, 도시: {city}"

# 위치 인수
print(introduce("Alice", 25))

# 키워드 인수
print(introduce(age=30, name="Bob", city="부산"))

# 혼합 사용 (위치 인수가 먼저)
print(introduce("Charlie", age=35, city="대구"))
가변 인수
# *args: 여러 개의 위치 인수
def sum_all(*numbers):
    return sum(numbers)

print(sum_all(1, 2, 3, 4, 5))  # 15
print(sum_all(10, 20))         # 30

# **kwargs: 여러 개의 키워드 인수
def print_info(**info):
    for key, value in info.items():
        print(f"{key}: {value}")

print_info(name="Alice", age=25, city="서울")
# name: Alice
# age: 25
# city: 서울

# 혼합 사용
def flexible_func(required, *args, **kwargs):
    print(f"필수: {required}")
    print(f"추가 위치 인수: {args}")
    print(f"키워드 인수: {kwargs}")

flexible_func("필수값", 1, 2, 3, name="Alice", age=25)

3.2 함수의 고급 기능

3.2.1 람다 함수

# 람다 함수 (익명 함수)
square = lambda x: x**2
print(square(5))  # 25

# 여러 매개변수
add = lambda x, y: x + y
print(add(3, 4))  # 7

# 함수의 인수로 사용
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, numbers))
print(squared)  # [1, 4, 9, 16, 25]

evens = list(filter(lambda x: x % 2 == 0, numbers))
print(evens)  # [2, 4]

3.2.2 내장 함수들

numbers = [1, 2, 3, 4, 5]

# map(): 각 요소에 함수 적용
def square(x):
    return x**2

squared = list(map(square, numbers))
print(squared)  # [1, 4, 9, 16, 25]

# filter(): 조건을 만족하는 요소만 필터링
def is_even(x):
    return x % 2 == 0

evens = list(filter(is_even, numbers))
print(evens)  # [2, 4]

# reduce(): 누적 연산 (functools 모듈 필요)
from functools import reduce

def add(x, y):
    return x + y

total = reduce(add, numbers)
print(total)  # 15

# sorted(): 정렬
students = [("Alice", 85), ("Bob", 92), ("Charlie", 78)]
sorted_by_grade = sorted(students, key=lambda x: x[1], reverse=True)
print(sorted_by_grade)  # [('Bob', 92), ('Alice', 85), ('Charlie', 78)]

3.2.3 함수의 스코프

# 전역 변수
global_var = "전역 변수"

def function1():
    # 지역 변수
    local_var = "지역 변수"
    print(f"함수 내부: {global_var}")
    print(f"함수 내부: {local_var}")

function1()
# print(local_var)  # NameError: 함수 외부에서 지역 변수 접근 불가

# global 키워드
counter = 0

def increment():
    global counter  # 전역 변수 수정
    counter += 1

increment()
print(counter)  # 1

# nonlocal 키워드 (중첩 함수)
def outer():
    x = 10
    
    def inner():
        nonlocal x  # 외부 함수의 변수 수정
        x += 1
        return x
    
    return inner

func = outer()
print(func())  # 11
print(func())  # 12

3.2.4 데코레이터 (기초)

# 간단한 데코레이터
def my_decorator(func):
    def wrapper():
        print("함수 실행 전")
        func()
        print("함수 실행 후")
    return wrapper

@my_decorator
def say_hello():
    print("안녕하세요!")

say_hello()
# 함수 실행 전
# 안녕하세요!
# 함수 실행 후

# 인수가 있는 함수용 데코레이터
def timer_decorator(func):
    import time
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        end = time.time()
        print(f"실행 시간: {end - start:.4f}초")
        return result
    return wrapper

@timer_decorator
def slow_function():
    import time
    time.sleep(1)
    return "완료"

result = slow_function()