콘텐츠로 이동

Chapter 07: 함수로 정리 - 코드의 레고 블록

Part 2: 프로젝트 도전


🎯 이 장에서 배우는 것

  • [ ] 함수를 정의하고 호출할 수 있다
  • [ ] 매개변수로 함수에 정보를 전달할 수 있다
  • [ ] 반환값으로 함수에서 결과를 받아올 수 있다
  • [ ] 기존 코드를 함수로 리팩토링할 수 있다
  • [ ] 나만의 함수 라이브러리를 만들 수 있다

💡 왜 이걸 배우나요?

지금까지 작성한 코드를 다시 살펴봐. LED 켜기, 센서 읽기, 조건 판단... 비슷한 코드가 여러 번 반복되지 않았어?

# 이런 코드가 여기저기 흩어져 있다면...
led.on()
time.sleep(0.5)
led.off()
time.sleep(0.5)

# 또 여기서도...
led.on()
time.sleep(0.5)
led.off()
time.sleep(0.5)

# 또 저기서도...
led.on()
time.sleep(0.5)
led.off()
time.sleep(0.5)

코드가 100줄, 200줄로 늘어나면? 😱 수정할 때 일일이 다 찾아서 고쳐야 해!

함수는 이런 문제를 해결해주는 마법 같은 도구야. 반복되는 코드를 레고 블록처럼 하나로 묶어서, 필요할 때마다 이름만 불러서 사용할 수 있거든.

flowchart LR A[📝 반복 코드] --> B[📦 함수로 묶기] B --> C[🎯 이름으로 호출] C --> D[✨ 깔끔한 코드] style A fill:#ffebee,stroke:#c62828 style B fill:#fff3e0,stroke:#f57c00 style C fill:#e3f2fd,stroke:#1976d2 style D fill:#e8f5e9,stroke:#388e3c

📚 핵심 개념

개념 1: 함수(Function)란?

  1. 비유로 시작: "함수는 마치 자판기와 같아요"
  2. 돈(입력)을 넣으면 → 자판기가 작동해서 → 음료(출력)가 나와
  3. 매번 직접 음료를 만들 필요 없이, 버튼만 누르면 끝!

  4. 정확한 정의: "정확히 말하면, 함수는 특정 작업을 수행하는 코드 블록에 이름을 붙인 것입니다"

  5. 한 번 만들어두면 이름을 불러서 반복 사용 가능
  6. 코드의 재사용성과 가독성을 높여줌

  7. 예시로 확인: "예를 들어, print()도 함수야!"

  8. print("안녕") - 괄호 안에 넣은 걸 화면에 출력해주는 함수
  9. 누군가 이미 만들어둔 함수를 우리가 사용하는 거지

쉽게 말하면: 자주 쓰는 코드에 이름표를 붙여서, 이름만 부르면 실행되게 하는 것!


개념 2: 함수의 구조

flowchart TB subgraph 함수정의["📦 함수 정의"] A["def 함수이름(매개변수):"] B[" 코드 블록"] C[" return 결과"] end subgraph 함수호출["🎯 함수 호출"] D["결과 = 함수이름(인자)"] end 함수정의 --> 함수호출 style A fill:#e3f2fd,stroke:#1976d2 style B fill:#fff3e0,stroke:#f57c00 style C fill:#e8f5e9,stroke:#388e3c style D fill:#f3e5f5,stroke:#7b1fa2

함수는 레시피와 같아:

레시피 함수
레시피 이름 함수 이름
재료 매개변수 (Parameter)
조리 과정 함수 본문 (코드)
완성된 요리 반환값 (Return)

쉽게 말하면: def로 레시피를 작성하고, 함수 이름으로 요리를 주문하는 것!


개념 3: 매개변수와 반환값

flowchart LR A["🥕 재료<br/>(매개변수)"] --> B["🍳 요리<br/>(함수 실행)"] B --> C["🍽️ 완성<br/>(반환값)"] style A fill:#ffecb3,stroke:#ff8f00 style B fill:#fff3e0,stroke:#f57c00 style C fill:#c8e6c9,stroke:#388e3c
  • 매개변수(Parameter): 함수에 전달하는 재료
  • 함수를 정의할 때 괄호 안에 적는 변수
  • def blink(times):times가 매개변수

  • 인자(Argument): 함수를 호출할 때 실제로 넣는 값

  • blink(5)5가 인자

  • 반환값(Return Value): 함수가 돌려주는 결과

  • return 키워드로 반환
  • 없으면 None 반환

쉽게 말하면: 재료(매개변수)를 넣으면 → 함수가 처리해서 → 결과(반환값)를 돌려줘!


🔨 따라하기

Step 1: 가장 간단한 함수 만들기

목표: 매개변수도 반환값도 없는 기본 함수 만들기

코드:

# === WHAT: 가장 간단한 함수 만들기 ===
# LED를 한 번 깜빡이는 함수를 만들어요

# --- WHY: 왜 필요한지 ---
# 깜빡임 코드를 매번 쓰지 않고, 이름만 불러서 실행하려고

from machine import Pin  # 핀 제어용
import time              # 시간 관련 기능

# LED 설정
led = Pin("LED", Pin.OUT)  # 내장 LED

# === 함수 정의 ===
def blink():               # def = 함수를 정의한다는 선언
    """LED를 한 번 깜빡입니다"""  # 함수 설명 (선택사항)
    led.on()               # LED 켜기
    time.sleep(0.3)        # 0.3초 대기
    led.off()              # LED 끄기
    time.sleep(0.3)        # 0.3초 대기
    print("깜빡!")         # 확인용 출력

# === 함수 호출 ===
print("함수 호출 전...")
blink()                    # 함수 이름으로 호출!
print("1번 깜빡 완료!")

blink()                    # 또 호출!
print("2번 깜빡 완료!")

blink()                    # 또 호출!
print("3번 깜빡 완료!")

실행 결과:

함수 호출 전...
깜빡!
1번 깜빡 완료!
깜빡!
2번 깜빡 완료!
깜빡!
3번 깜빡 완료!

여기서 잠깐! 🤔 - def blink(): - 함수를 정의만 한 거야. 아직 실행 안 됨! - blink() - 이때 비로소 함수가 실행돼! - 괄호 ()를 빼면 함수가 실행되지 않아! blink만 쓰면 "이런 함수가 있다"는 정보만 나와


Step 2: 매개변수 사용하기

목표: 깜빡이는 횟수를 지정할 수 있게 만들기

코드:

# === WHAT: 매개변수가 있는 함수 ===
# 깜빡이는 횟수를 지정할 수 있어요

# --- WHY: 왜 필요한지 ---
# 상황에 따라 다른 횟수로 깜빡이고 싶어서

from machine import Pin
import time

led = Pin("LED", Pin.OUT)

# === 매개변수가 있는 함수 ===
def blink(times):          # times가 매개변수!
    """LED를 지정한 횟수만큼 깜빡입니다

    times: 깜빡일 횟수
    """
    for i in range(times):     # times번 반복
        led.on()
        time.sleep(0.2)
        led.off()
        time.sleep(0.2)
    print(f"{times}번 깜빡 완료!")

# === 다양한 호출 ===
blink(3)    # 3번 깜빡 (3이 times에 전달됨)
blink(5)    # 5번 깜빡
blink(1)    # 1번 깜빡

# 변수로도 전달 가능!
count = 10
blink(count)  # 10번 깜빡

실행 결과:

3번 깜빡 완료!
5번 깜빡 완료!
1번 깜빡 완료!
10번 깜빡 완료!

여기서 잠깐! 🤔 - times매개변수 - 함수 정의에서 사용 - 3, 5, 1, count인자 - 함수 호출할 때 전달하는 실제 값 - 함수가 호출될 때마다 times에 다른 값이 들어가!


Step 3: 여러 매개변수 사용하기

목표: 횟수와 속도를 모두 지정할 수 있게 만들기

코드:

# === WHAT: 여러 매개변수를 받는 함수 ===
# 횟수와 속도를 모두 지정할 수 있어요

# --- WHY: 왜 필요한지 ---
# 더 유연하게 깜빡임을 제어하고 싶어서

from machine import Pin
import time

led = Pin("LED", Pin.OUT)

# === 여러 매개변수 ===
def blink(times, speed):   # 쉼표로 구분해서 여러 개!
    """LED를 지정한 횟수와 속도로 깜빡입니다

    times: 깜빡일 횟수
    speed: 깜빡임 간격 (초 단위)
    """
    print(f"속도 {speed}초로 {times}번 깜빡이기 시작!")
    for i in range(times):
        led.on()
        time.sleep(speed)
        led.off()
        time.sleep(speed)
    print("완료!")

# === 호출 ===
blink(3, 0.5)      # 3번, 0.5초 간격 (느리게)
blink(5, 0.1)      # 5번, 0.1초 간격 (빠르게)
blink(2, 1.0)      # 2번, 1초 간격 (아주 느리게)

실행 결과:

속도 0.5초로 3번 깜빡이기 시작!
완료!
속도 0.1초로 5번 깜빡이기 시작!
완료!
속도 1.0초로 2번 깜빡이기 시작!
완료!

여기서 잠깐! 🤔 매개변수 순서가 중요해! blink(3, 0.5)에서: - 3은 첫 번째 매개변수 times에 - 0.5는 두 번째 매개변수 speed에 전달돼


Step 4: 기본값 설정하기

목표: 매개변수에 기본값을 줘서 더 편리하게 만들기

코드:

# === WHAT: 기본값이 있는 매개변수 ===
# 인자를 안 넣으면 기본값이 사용돼요

# --- WHY: 왜 필요한지 ---
# 매번 모든 값을 넣기 귀찮을 때, 자주 쓰는 값을 기본으로

from machine import Pin
import time

led = Pin("LED", Pin.OUT)

# === 기본값 설정 ===
def blink(times=3, speed=0.3):  # = 뒤에 기본값!
    """LED를 깜빡입니다

    times: 깜빡일 횟수 (기본 3번)
    speed: 깜빡임 간격 (기본 0.3초)
    """
    print(f"{speed}초 간격으로 {times}번 깜빡이기!")
    for i in range(times):
        led.on()
        time.sleep(speed)
        led.off()
        time.sleep(speed)

# === 다양한 호출 방법 ===
blink()           # 기본값 사용: 3번, 0.3초
blink(5)          # times만 지정: 5번, 0.3초
blink(2, 0.1)     # 둘 다 지정: 2번, 0.1초

# 이름으로 지정하기 (키워드 인자)
blink(speed=0.5)         # times는 기본값, speed만 지정
blink(times=10, speed=0.05)  # 둘 다 이름으로 지정

실행 결과:

0.3초 간격으로 3번 깜빡이기!
0.3초 간격으로 5번 깜빡이기!
0.1초 간격으로 2번 깜빡이기!
0.5초 간격으로 3번 깜빡이기!
0.05초 간격으로 10번 깜빡이기!

여기서 잠깐! 🤔 - 기본값이 있는 매개변수는 뒤쪽에 와야 해! - def blink(times=3, speed): ← 이건 에러! - def blink(times, speed=0.3): ← 이건 OK!


Step 5: 반환값 사용하기

목표: 함수에서 계산 결과를 돌려받기

코드:

# === WHAT: 반환값이 있는 함수 ===
# 함수가 결과를 돌려줘요

# --- WHY: 왜 필요한지 ---
# 함수 안에서 계산한 결과를 밖에서 사용하고 싶어서

from machine import Pin, ADC
import time

# 조도 센서 설정 (A0에 연결)
light_sensor = ADC(Pin(26))

# === 반환값이 있는 함수 ===
def read_light():
    """조도 센서 값을 읽어서 반환합니다

    반환: 조도 값 (0~65535)
    """
    value = light_sensor.read_u16()  # 센서 읽기
    return value                      # 값을 반환!

def light_to_percent(raw_value):
    """조도 값을 퍼센트로 변환합니다

    raw_value: 원본 센서 값 (0~65535)
    반환: 퍼센트 값 (0~100)
    """
    percent = raw_value / 65535 * 100
    return round(percent, 1)  # 소수점 1자리로 반올림해서 반환

# === 반환값 사용하기 ===
# 방법 1: 변수에 저장
raw = read_light()
print(f"원본 값: {raw}")

# 방법 2: 바로 다른 함수에 전달
percent = light_to_percent(read_light())
print(f"밝기: {percent}%")

# 방법 3: 조건문에서 사용
if read_light() > 30000:
    print("밝아요!")
else:
    print("어두워요!")

실행 결과 (환경에 따라 다름):

원본 값: 45230
밝기: 69.0%
밝아요!

여기서 잠깐! 🤔 - return을 만나면 함수가 즉시 종료돼! - return 뒤의 코드는 실행되지 않아 - return이 없으면 None을 반환해

def test():
    print("1번")
    return "끝"
    print("2번")  # 이건 절대 실행 안 됨!

result = test()  # "1번" 출력
print(result)    # "끝" 출력

Step 6: 여러 값 반환하기

목표: 하나의 함수에서 여러 결과를 동시에 반환하기

코드:

# === WHAT: 여러 값을 반환하는 함수 ===
# 튜플로 여러 값을 한꺼번에 반환해요

# --- WHY: 왜 필요한지 ---
# 온도와 습도처럼 여러 값을 함께 얻고 싶을 때

from machine import Pin
import time

# DHT11 센서 시뮬레이션 (실제 센서가 없을 때)
# 실제 사용 시에는 dht 라이브러리 사용

def read_environment():
    """온도와 습도를 읽어서 반환합니다

    반환: (온도, 습도) 튜플
    """
    # 시뮬레이션 값 (실제로는 센서에서 읽기)
    temperature = 25.5
    humidity = 60.0
    return temperature, humidity  # 여러 값 반환!

def analyze_comfort(temp, humid):
    """온습도로 쾌적도를 분석합니다

    temp: 온도
    humid: 습도
    반환: (쾌적도 점수, 메시지)
    """
    score = 100

    # 온도 분석
    if temp < 18 or temp > 28:
        score -= 30
    elif temp < 20 or temp > 26:
        score -= 10

    # 습도 분석
    if humid < 40 or humid > 70:
        score -= 30
    elif humid < 45 or humid > 65:
        score -= 10

    # 메시지 결정
    if score >= 80:
        message = "쾌적해요! 😊"
    elif score >= 60:
        message = "괜찮아요 🙂"
    else:
        message = "조금 불편해요 😓"

    return score, message  # 두 값 반환

# === 여러 값 받기 ===
# 방법 1: 여러 변수로 받기
temp, humid = read_environment()
print(f"온도: {temp}°C, 습도: {humid}%")

# 방법 2: 튜플로 받기
result = read_environment()
print(f"결과: {result}")       # (25.5, 60.0)
print(f"온도: {result[0]}°C")  # 인덱스로 접근

# === 연결해서 사용하기 ===
temp, humid = read_environment()
score, message = analyze_comfort(temp, humid)
print(f"쾌적도: {score}점 - {message}")

실행 결과:

온도: 25.5°C, 습도: 60.0%
결과: (25.5, 60.0)
온도: 25.5°C
쾌적도: 100점 - 쾌적해요! 😊

여기서 잠깐! 🤔 return a, b는 실제로 return (a, b) - 튜플을 반환하는 거야! 받을 때 x, y = 함수()로 풀어서 받을 수 있어 (언패킹)


Step 7: 기존 코드를 함수로 리팩토링하기

목표: 이전에 작성한 자동 야간등 코드를 함수로 깔끔하게 정리하기

리팩토링 전 (6차시 코드):

# 지저분한 코드 😓
from machine import Pin, ADC, PWM
import time

light_sensor = ADC(Pin(26))
led = PWM(Pin(15))
led.freq(1000)

while True:
    light_value = light_sensor.read_u16()

    # 밝기 계산 (반복되는 패턴)
    if light_value < 10000:
        brightness = 65535
    elif light_value < 30000:
        brightness = 40000
    elif light_value < 50000:
        brightness = 20000
    else:
        brightness = 0

    led.duty_u16(brightness)

    # 출력 (또 반복...)
    print(f"조도: {light_value}, LED: {brightness}")

    time.sleep(0.5)

리팩토링 후:

# === WHAT: 함수로 정리한 자동 야간등 ===
# 깔끔하게 정리된 코드 ✨

# --- WHY: 왜 필요한지 ---
# 각 기능이 분리되어 읽기 쉽고, 수정도 쉬워요

from machine import Pin, ADC, PWM
import time

# === 하드웨어 설정 ===
light_sensor = ADC(Pin(26))
led = PWM(Pin(15))
led.freq(1000)

# === 함수 정의 ===
def read_light():
    """조도 센서 값을 읽습니다"""
    return light_sensor.read_u16()

def calculate_brightness(light_value):
    """조도에 따른 LED 밝기를 계산합니다

    light_value: 조도 센서 값
    반환: LED 밝기 (0~65535)
    """
    if light_value < 10000:      # 아주 어두움
        return 65535             # 최대 밝기
    elif light_value < 30000:    # 어두움
        return 40000
    elif light_value < 50000:    # 약간 어두움
        return 20000
    else:                        # 밝음
        return 0                 # LED 끄기

def set_led_brightness(brightness):
    """LED 밝기를 설정합니다"""
    led.duty_u16(brightness)

def display_status(light, brightness):
    """현재 상태를 출력합니다"""
    percent = round(light / 65535 * 100, 1)
    led_percent = round(brightness / 65535 * 100, 1)
    print(f"조도: {percent}% → LED: {led_percent}%")

# === 메인 루프 ===
def main():
    """자동 야간등 메인 함수"""
    print("🌙 자동 야간등 시작!")
    print("-" * 30)

    while True:
        # 1. 센서 읽기
        light = read_light()

        # 2. 밝기 계산
        brightness = calculate_brightness(light)

        # 3. LED 설정
        set_led_brightness(brightness)

        # 4. 상태 출력
        display_status(light, brightness)

        time.sleep(0.5)

# 프로그램 시작
main()

여기서 잠깐! 🤔

리팩토링의 장점을 비교해보자:

flowchart TB subgraph before["❌ 리팩토링 전"] A1["모든 코드가<br/>한 덩어리"] A2["수정할 때<br/>전체를 읽어야 함"] A3["재사용 불가"] end subgraph after["✅ 리팩토링 후"] B1["기능별로<br/>분리됨"] B2["필요한 함수만<br/>수정"] B3["다른 프로젝트에<br/>재사용 가능"] end before --> |"함수로 정리"| after style A1 fill:#ffcdd2,stroke:#c62828 style A2 fill:#ffcdd2,stroke:#c62828 style A3 fill:#ffcdd2,stroke:#c62828 style B1 fill:#c8e6c9,stroke:#388e3c style B2 fill:#c8e6c9,stroke:#388e3c style B3 fill:#c8e6c9,stroke:#388e3c

📝 전체 코드

나만의 피코 라이브러리

# === my_pico_lib.py ===
# 나만의 피코 함수 라이브러리
# 자주 쓰는 기능을 함수로 모아놨어요!

from machine import Pin, ADC, PWM
import time

# ===== LED 관련 함수 =====

def setup_led(pin_num="LED"):
    """LED를 설정하고 반환합니다"""
    return Pin(pin_num, Pin.OUT)

def blink(led, times=3, speed=0.3):
    """LED를 깜빡입니다

    led: LED 핀 객체
    times: 깜빡일 횟수 (기본 3)
    speed: 간격 (기본 0.3초)
    """
    for _ in range(times):
        led.on()
        time.sleep(speed)
        led.off()
        time.sleep(speed)

def sos_signal(led):
    """SOS 신호를 보냅니다 (... --- ...)"""
    # S: 짧게 3번
    blink(led, 3, 0.1)
    time.sleep(0.3)
    # O: 길게 3번
    blink(led, 3, 0.4)
    time.sleep(0.3)
    # S: 짧게 3번
    blink(led, 3, 0.1)

# ===== 센서 관련 함수 =====

def setup_light_sensor(pin_num=26):
    """조도 센서를 설정하고 반환합니다"""
    return ADC(Pin(pin_num))

def read_light_percent(sensor):
    """조도를 퍼센트로 반환합니다 (0~100)"""
    raw = sensor.read_u16()
    return round(raw / 65535 * 100, 1)

def get_light_level(percent):
    """조도 퍼센트를 텍스트로 변환합니다"""
    if percent < 20:
        return "아주 어두움 🌑"
    elif percent < 40:
        return "어두움 🌙"
    elif percent < 60:
        return "보통 🌤️"
    elif percent < 80:
        return "밝음 ☀️"
    else:
        return "아주 밝음 🌟"

# ===== PWM LED 관련 함수 =====

def setup_pwm_led(pin_num, freq=1000):
    """PWM LED를 설정하고 반환합니다"""
    pwm = PWM(Pin(pin_num))
    pwm.freq(freq)
    return pwm

def set_brightness(pwm_led, percent):
    """LED 밝기를 퍼센트로 설정합니다 (0~100)"""
    duty = int(percent / 100 * 65535)
    pwm_led.duty_u16(duty)

def fade_in(pwm_led, duration=1.0, steps=20):
    """LED를 서서히 켭니다"""
    delay = duration / steps
    for i in range(steps + 1):
        brightness = i / steps * 100
        set_brightness(pwm_led, brightness)
        time.sleep(delay)

def fade_out(pwm_led, duration=1.0, steps=20):
    """LED를 서서히 끕니다"""
    delay = duration / steps
    for i in range(steps, -1, -1):
        brightness = i / steps * 100
        set_brightness(pwm_led, brightness)
        time.sleep(delay)

# ===== 유틸리티 함수 =====

def map_value(value, from_min, from_max, to_min, to_max):
    """값을 한 범위에서 다른 범위로 변환합니다

    예: map_value(50, 0, 100, 0, 255) → 127.5
    """
    return (value - from_min) / (from_max - from_min) * (to_max - to_min) + to_min

def constrain(value, min_val, max_val):
    """값을 지정된 범위 내로 제한합니다"""
    return max(min_val, min(max_val, value))

# ===== 테스트 =====
if __name__ == "__main__":
    # 이 파일을 직접 실행했을 때만 테스트
    print("📚 my_pico_lib 테스트")
    print("-" * 30)

    # LED 테스트
    led = setup_led()
    print("LED 깜빡이기...")
    blink(led, 3, 0.2)

    # 조도 센서 테스트 (연결된 경우)
    try:
        light = setup_light_sensor()
        percent = read_light_percent(light)
        level = get_light_level(percent)
        print(f"조도: {percent}% - {level}")
    except:
        print("조도 센서 없음")

    print("-" * 30)
    print("✅ 테스트 완료!")

라이브러리 사용 예제

# === main.py ===
# 라이브러리를 활용한 자동 야간등

from my_pico_lib import *  # 모든 함수 가져오기

# 하드웨어 설정
led = setup_led()
pwm_led = setup_pwm_led(15)
light_sensor = setup_light_sensor(26)

# 시작 신호
print("🌙 자동 야간등 시작!")
blink(led, 2, 0.2)  # 시작 표시

while True:
    # 조도 읽기
    light = read_light_percent(light_sensor)
    level = get_light_level(light)

    # 조도에 따라 LED 밝기 설정
    # 어두울수록 LED를 밝게 (반비례)
    led_brightness = constrain(100 - light, 0, 100)
    set_brightness(pwm_led, led_brightness)

    # 상태 출력
    print(f"조도: {light}% ({level}) → LED: {led_brightness}%")

    time.sleep(0.5)

⚠️ 자주 하는 실수

실수 1: 함수 호출 시 괄호 빼먹기

증상: 함수가 실행되지 않고, 이상한 출력이 나옴

<function blink at 0x20002a40>

원인: 괄호 ()를 빼먹으면 함수 자체를 출력함

해결:

# 잘못된 코드
blink          # 괄호 없음 - 함수 실행 안 됨!
print(blink)   # 함수 객체 정보만 출력

# 올바른 코드
blink()        # 괄호 있음 - 함수 실행!
print(blink()) # 함수 실행 후 반환값 출력


실수 2: 매개변수 순서 헷갈리기

증상: 의도와 다르게 동작함

원인: 매개변수 순서를 잘못 넣음

해결:

def blink(times, speed):
    pass

# 잘못된 코드
blink(0.3, 5)  # 0.3번 깜빡이기? 5초 간격?? 🤔

# 올바른 코드
blink(5, 0.3)  # 5번, 0.3초 간격 ✓

# 더 안전한 방법: 키워드 인자 사용
blink(times=5, speed=0.3)  # 명확함!
blink(speed=0.3, times=5)  # 순서 바꿔도 OK!


실수 3: 반환값 무시하기

증상: 계산 결과가 사라짐

원인: return으로 돌려준 값을 받지 않음

해결:

def calculate_brightness(light):
    return 65535 - light

# 잘못된 코드
calculate_brightness(30000)  # 결과가 사라짐!
print("밝기를 계산했어요")   # 근데 결과는 어디?

# 올바른 코드
brightness = calculate_brightness(30000)  # 변수에 저장!
print(f"밝기: {brightness}")


실수 4: 함수 안에서 만든 변수를 밖에서 사용

증상: NameError: name 'xxx' is not defined

원인: 함수 안에서 만든 변수는 함수 밖에서 사용 불가 (지역 변수)

해결:

# 잘못된 코드
def calculate():
    result = 100    # 함수 안에서만 존재

calculate()
print(result)       # 에러! result는 함수 밖에 없어

# 올바른 코드
def calculate():
    result = 100
    return result   # 반환으로 내보내기

value = calculate() # 반환값 받기
print(value)        # OK!


실수 5: return 후에 코드 작성

증상: 일부 코드가 실행되지 않음

원인: return을 만나면 함수가 즉시 종료됨

해결:

# 잘못된 코드
def process():
    return "결과"
    print("처리 완료!")  # 절대 실행 안 됨!

# 올바른 코드
def process():
    print("처리 완료!")  # 먼저 실행
    return "결과"        # 마지막에 반환


✅ 스스로 점검하기

1. 다음 코드의 출력 결과는?

def greet(name="학생"):
    return f"안녕, {name}!"

print(greet())
print(greet("철수"))

2. 이 함수의 문제점은 무엇일까?

def add_and_print(a, b):
    result = a + b
    print(f"결과: {result}")

3. 매개변수와 인자의 차이점을 설명해보세요.

정답 확인 **1번 답**:
안녕, 학생!
안녕, 철수!
- 첫 번째 호출: 인자 없음 → 기본값 "학생" 사용 - 두 번째 호출: "철수"가 name에 전달됨 **2번 답**: - 문제: `return`이 없어서 결과를 밖에서 사용할 수 없음 - `print()`는 화면에 출력만 하고, 값을 돌려주지 않음 - 수정: `return result` 추가
def add_and_print(a, b):
    result = a + b
    print(f"결과: {result}")
    return result  # 이게 있어야 결과를 받을 수 있음
**3번 답**: - **매개변수(Parameter)**: 함수를 **정의**할 때 괄호 안에 쓰는 변수 - `def greet(name):` ← `name`이 매개변수 - **인자(Argument)**: 함수를 **호출**할 때 전달하는 실제 값 - `greet("철수")` ← `"철수"`가 인자 쉽게 기억하기: 매개변수는 "재료 목록", 인자는 "실제 재료"

🚀 더 해보기

도전 1: 온도 변환 함수 만들기

섭씨를 화씨로, 화씨를 섭씨로 변환하는 함수를 만들어보세요.

# 힌트
# 화씨 = 섭씨 × 9/5 + 32
# 섭씨 = (화씨 - 32) × 5/9

def celsius_to_fahrenheit(celsius):
    # 여기에 코드 작성
    pass

def fahrenheit_to_celsius(fahrenheit):
    # 여기에 코드 작성
    pass

# 테스트
print(celsius_to_fahrenheit(0))   # 32.0
print(celsius_to_fahrenheit(100)) # 212.0
print(fahrenheit_to_celsius(32))  # 0.0
print(fahrenheit_to_celsius(98.6)) # 37.0

도전 2: 버튼 카운터 함수 만들기

버튼을 누른 횟수를 세고, 일정 횟수마다 LED 패턴을 바꾸는 프로그램을 함수로 구현해보세요.

# 힌트 구조
def read_button():
    """버튼 상태를 읽고 눌림 여부 반환"""
    pass

def count_press(current, pressed):
    """버튼이 눌리면 카운트 증가"""
    pass

def get_pattern(count):
    """카운트에 따른 LED 패턴 반환"""
    # 5번마다 다른 패턴
    pass

def play_pattern(pattern):
    """패턴에 맞게 LED 동작"""
    pass

도전 3: 나만의 피코 라이브러리 확장하기 ⭐

my_pico_lib.py에 다음 함수들을 추가해보세요:

  1. 버저 관련 함수
  2. setup_buzzer(pin_num) - 버저 설정
  3. beep(buzzer, frequency, duration) - 특정 주파수로 울리기
  4. play_melody(buzzer, notes) - 멜로디 연주

  5. RGB LED 관련 함수

  6. setup_rgb_led(r_pin, g_pin, b_pin) - RGB LED 설정
  7. set_color(rgb, r, g, b) - 색상 설정
  8. rainbow_cycle(rgb, speed) - 무지개 색상 순환

  9. 환경 분석 함수

  10. read_environment() - 온도, 습도, 조도 한번에 읽기
  11. analyze_comfort(temp, humid) - 쾌적도 분석
  12. suggest_action(comfort_score) - 행동 제안

🔗 다음 장으로

축하해! 🎉 이제 함수라는 강력한 도구를 사용할 수 있게 됐어!

이번 장에서 배운 것: - def로 함수 정의하기 - 매개변수로 재료 전달하기 - return으로 결과 돌려받기 - 기본값으로 편리하게 만들기 - 기존 코드를 함수로 리팩토링하기

다음 장 미리보기:

8-9차시는 미니 프로젝트 시간이야! 지금까지 배운 모든 것을 총동원해서 나만의 작품을 만들어볼 거야.

  • 스마트 무드등 🌈
  • 반응형 알람 ⏰
  • 또는 네가 상상하는 어떤 것이든!

오늘 만든 my_pico_lib.py를 활용하면 프로젝트가 훨씬 수월해질 거야!