제로베이스 데이터 파트타임 스쿨 학습 일지 [25.03.29]

[강의 요약]

[Ch 03. 파이썬 중급] 강의 수강

05_데이터 반환부터 11_모듈사용까지 강의 수강하였음

주말이어서 평일보다 더 강의를 수강했다.
다음 주 자격증 시험이 없었으면 더 많은 시간을 할당할 수 있을 텐데 아쉽다.

 

 

 

[데이터 반환]

  • 함수 실행 결과 반환
    • return 키워드를 이용하면 함수 실행 결과를 호출부로 반환할 수 있다.
    • 함수를 실행한 결과를 함수 바깥으로 전달하는 것
  • 기본 사용법
def calculator(n1, n2):
    result = n1 + n2
    return result

위 함수는 n1 + n2 값을 계산하고, 그 결과를 return을 통해 함수 바깥으로 전달한다.

# 만든 함수 사용한 코드
returnValue = calculator(20, 10)
print(f'returnValue: {returnValue}')

 

●코드 실행 결과 

returnValue: 30

★코드 설명★

calculator(20, 10)의 실행 결과 30return 되고

returnValue에 저장되어서 출력된다.

 

 

 

  • 조건에 따라 다른 값 반환하기
    • 함수가 return을 만나면 실행을 종료한다.
def divideNumber(n):
    if n % 2 == 0:
        return '짝수'
    else:
        return '홀수'

위 코드에서 짝수이면 '짝수'를, 홀수이면 '홀수'를 반환한다.

return을 만나면 함수는 그 자리에서 실행종료 된다.

returnValue = divideNumber(5)
print(f'returnValue: {returnValue}')

●코드 실행 결과 

returnValue: 홀수

 

 

 

  • 반환 없이 print()만 있는 함수와의 차이
    • print()는 결과를 화면에 출력만 함
    • return은 값을 함수 바깥으로 넘겨줌
def show():
    print("Hello")    # 출력만 함

def give():
    return "Hello"    # 값을 돌려줌

x = show()      # x는 None
y = give()      # y는 "Hello"

★코드 설명★

  • x = show() 실행
    • show()를 호출
    • Hello 출력됨
    • 그 후 return이 없으므로 자동으로 None을 반환
  • y = give() 실행
    • give()를 호출
    • "Hello"라는 문자열을 반환
    • y에 "Hello"라는 값이 저장됨

 

print(f"x의 값: {x}")
print(f"y의 값: {y}")

확인하기 위해 위 코드를 실행시켜 보면

x의 값: None
y의 값: Hello

이렇게 출력되는 것을 확인할 수 있다.

 

 

 

 

[지역 변수와 전역 변수]

  • 전역 변수
    • 함수 밖에서 선언된 변수
    • 어디서든 읽을 수 있지만, 함수 안에서 수정할 수 없다.
      • 값을 변경하려면 global을 사용해야 함
num_out = 10  # 전역 변수

def printNumbers():
    print(f'num_out: {num_out}')  # 사용 가능 (읽기만 함)

printNumbers()
print(f'num_out: {num_out}')

●코드 실행 결과 

num_out: 10
num_out: 10

★코드 설명★

함수 안에서 전역 변수 값을 읽을 수는 있다.

 

 

 

  • 함수 안에서 전역변수를 수정하려고 하는 경우
    • 전역 변수의 값은 바뀌지 않음
    • 함수 안에서 같은 이름으로 새로운 지역 변수가 생긴 것
num_out = 10

def printNumbers():
    num_out = 20  # 함수 안에서 새 지역 변수를 만들어버림!
    print(f'num_out: {num_out}')

printNumbers()
print(f'num_out: {num_out}')

●코드 실행 결과 

num_out: 20
num_out: 10

 

 

 

  • 지역 변수
    • 함수 안에서 선언된 변수
    • 그 함수 안에서만 사용할 수 있다.
def printNumbers():
    num_in = 20
    print(f'num_in: {num_in}')

printNumbers()
print(f'num_in: {num_in}')  # 이렇게하면 오류!!

●코드 실행 결과 

num_in: 20
NameError: name 'num_in' is not defined

★코드 설명★

지역 변수는 함수 바깥에서는 쓸 수 없다!

 

 

 

  • global 키워드
    • 함수 안에서 전역 변수의 값을 변경하고 싶을 때 사용하는 키워드
num_out = 10

def printNumbers():
    global num_out  # 전역 변수라고 알려줌!
    num_out = 20
    print(f'num_out: {num_out}')

printNumbers()
print(f'num_out: {num_out}')

●코드 실행 결과 

num_out: 20
num_out: 20

★코드 설명★

전역 변수의 값을 함수 안에서 바꿀 수 있게 됨

 

 

 

 

[중첩함수]

  • 중첩함수란?
    • Nested Function
    • 함수 안에 또 다른 함수가 있는 형태
  • 왜 사용할까?
    • 함수 안에서만 쓰는 보조 기능을 함수로 따로 나눌 수 있음
    • 코드 보안성, 구조가 더 깔끔해지고 명확해지는 장점이 있음
def out_function():                  # 외부 함수
    print('out_function called!!')

    def in_function():              # 내부 함수 (중첩 함수)
        print('in_function called!!')

    in_function()                  # 중첩 함수는 외부 함수 안에서만 호출 가능

out_function()

●코드 실행 결과 

out_function called!!
in_function called!!

★코드 설명★

  • 외부함수
    • out_function()처럼 일반적인 함수
  • 중첩 함수
    • 외부 함수 안에서 정의된 in_function()
  • 호출 위치
    • 중첩 함수는 외부 함수 안에서만 호출할 수 있음
  • in_function()를 외부에서 호출한다면 에러가 발생한다.
    • 외부에서는 직접 접근 불가능함

요약하면 중첩 함수는 "도움을 주는 조수"처럼, 외부 함수 안에서만 일한다.

 

 

  • 중첩 함수 실습 코드
    • 계산기 프로그램
def calculator(n1, n2, operator):
    # 덧셈 함수
    def addCal():
        print(f'덧셈 연산: {round(n1 + n2, 2)}')

    # 뺄셈 함수
    def subCal():
        print(f'뺄셈 연산: {round(n1 - n2, 2)}')

    # 곱셈 함수
    def mulCal():
        print(f'곱셈 연산: {round(n1 * n2, 2)}')

    # 나눗셈 함수
    def divCal():
        print(f'나눗셈 연산: {round(n1 / n2, 2)}')

    # 사용자의 선택에 따라 중첩 함수 호출
    if operator == 1:
        addCal()
    elif operator == 2:
        subCal()
    elif operator == 3:
        mulCal()
    elif operator == 4:
        divCal()
    else:
        print("잘못된 연산자입니다.")

●함수 호출 예시 

calculator(10, 5, 1)  # 덧셈
calculator(10, 5, 2)  # 뺄셈
calculator(10, 5, 3)  # 곱셈
calculator(10, 5, 4)  # 나눗셈

●코드 실행 결과 

덧셈 연산: 15.0
뺄셈 연산: 5.0
곱셈 연산: 50.0
나눗셈 연산: 2.0

 

 

 

 

[lambda 함수]

  • lambda 함수란?
    • 함수를 한 줄로 간단하게 만들 수 있는 키워드
    • 보통 def로 만드는 일반 함수보다 짧고 간단한 연산용 함수를 만들 때 유용함
    • 간단한 함수 생성, 함수형 프로그래밍, 일회성 처리의 용도
    • return 사용하지 않고 오직 한 줄만 가능
  • 언제 사용하면 좋을까?
    • 함수가 한 줄로 끝날 때 : 간단하게 표현 가능
    • 일회성 계산이나 간단한 연산 : 굳이 def로 이름 붙일 필요 없음
    • 함수를 변수에 저장해서 쓸 때 : 함수처럼 사용 가능

 

  • lambda 함수 기본 문법
# 기본 문법
lambda 매개변수1, 매개변수2: 연산 또는 리턴값

# 예시
lambda x, y: x + y

# 일반 함수로 한다면?
def 함수(x, y):
    return x + y

 

 

  • 일반 함수와 lambda 함수 비교
# 일반 함수 예시
def calculator(n1, n2):
    return n1 + n2

returnValue = calculator(10, 20)
print(f'returnValue: {returnValue}')

●일반 함수 코드 실행 결과 

returnValue: 30

 

# lambda 함수 예시
calculator = lambda n1, n2: n1 + n2

returnValue = calculator(10, 20)
print(f'returnValue: {returnValue}')

●lambda 함수 코드 실행 결과 

returnValue: 30

 

 

  • 실습 코드 : 도형 넓이 계산기
# lambda 함수 부분
getTriangleArea = lambda n1, n2: n1 * n2 / 2
getSquareArea  = lambda n1, n2: n1 * n2
getCircleArea  = lambda r: r * r * 3.14

# 입력 및 실행
width = int(input('가로 길이 입력: '))
height = int(input('세로 길이 입력: '))
radius = int(input('반지름 길이 입력: '))

triangleValue = getTriangleArea(width, height)
squareValue = getSquareArea(width, height)
circleValue = getCircleArea(radius)

print(f'삼각형 넓이: {triangleValue}')
print(f'사각형 넓이: {squareValue}')
print(f'원 넓이: {circleValue}')

●코드 실행 결과 

가로 길이 입력: 20  
세로 길이 입력: 30  
반지름 길이 입력: 6

삼각형 넓이: 300.0  
사각형 넓이: 600  
원 넓이: 113.04

 

 

 

 

[모듈]

  • 모듈이란?
    • 다른 사람이 미리 만들어 놓은 코드 묶음
    • 필요할 때 가져다 쓰는 도구 상자 같은 존재
# 예: random 모듈 사용
# import 모듈명
import random
print(random.randint(1, 10))
  • random, math, datetime 등 이미 만들어진 모듈을 import 해서 사용
  • 이미 잘 만들어진 기능을 가져다 쓸 수 있음

 

  • 모듈의 종류
    • 파이썬에서 사용하는 모듈은 크게 3가지
    • 내부 모듈
      • 파이썬 설치 시 기본 포함 (예: random, math, datetime)
    • 외부 모듈
      • 따로 설치해서 사용하는 모듈 (예: pandas, numpy, requests)
    • 사용자 모듈
      • 사용자가 직접 만든 .py 파일 (예: my_md.py 등)

 

 

  • 실습 코드 : 랜덤 숫자 1개 뽑기
import random

rNum = random.randint(1, 10)  # 1부터 10 사이 정수 중 1개 랜덤 반환
print(f'rNum: {rNum}')

●코드 실행 결과 

rNum: 7

 

 

  • 실습 코드 : 랜덤 숫자 10개 뽑기
import random

rNums = random.sample(range(1, 101), 10)  # 1~100 중 10개 중복 없이 랜덤 선택
print(f'rNums: {rNums}')

●코드 실행 결과 

rNums: [45, 3, 91, 7, 68, 55, 16, 1, 28, 82]

 

 

 

 

[모듈제작]

  • 모듈 제작은 어떻게 할까?
    • 특정 기능을 따로 .py 파일로 저장해 놓고 필요할 때 import 해서 쓰는 것
    • 모듈은 함수 묶음이 들어있는 파일
    • 다른 Python 파일에서 import 파일명으로 모듈 불러와 사용 가능
      • 함수 호출은 모듈이름.함수이름()
  • 코드 재사용, 기능 분리, 유지보수 용이가 장점
    • 프로그램이 커지면 기능별로 모듈로 나눠 관리하는 게 필수
    • 협업할 때도 모듈로 나누면 역할 분담이 쉬워짐!

 

 

  • 실습 코드 : 사칙연산 모듈 만들기
    • 기능을 여러 곳에서 재사용할 수 있음 (코드 재활용)
# calculator.py (모듈 파일)
def add(n1, n2):
    print(f'덧셈 결과: {n1 + n2}')

def sub(n1, n2):
    print(f'뺄셈 결과: {n1 - n2}')

def mul(n1, n2):
    print(f'곱셈 결과: {n1 * n2}')

def div(n1, n2):
    print(f'나눗셈 결과: {round(n1 / n2, 2)}')
# module.py (사용 파일)
import calculator

calculator.add(20, 10)
calculator.sub(20, 10)
calculator.mul(20, 10)
calculator.div(20, 10)

 

 

  • 실습 코드 : 로또 번호 추첨 모듈
# lottoMachine.py
import random

def getLottoNumbers():
    result = random.sample(range(1, 46), 6)
    return result
# main.py
import lottoMachine

lottoNumbers = lottoMachine.getLottoNumbers()
print(f'lottoNumbers: {lottoNumbers}')
# 출력 예시
lottoNumbers: [3, 14, 28, 33, 41, 44]

 

 

  • 실습 코드 : 로또 번호 추첨 모듈
# reverseStr.py
def reverseStr(str):
    reversedString = ''
    for c in str:
        reversedString = c + reversedString
    return reversedString
# main.py
import reverseStr

userInputStr = input('문자열 입력: ')
reversedString = reverseStr.reverseStr(userInputStr)
print(f'reversedString: {reversedString}')
# 출력 예시
문자열 입력: hello
reversedString: olleh

 

 

 

 

[모듈사용]

  • 모듈 사용은 어떻게 할까?
    • 여러 키워드 사용
    • import 키워드
    • import ~ as ~ 키워드
    • from ~ import ~ 키워드

 

import calculator

calculator.add(10, 20)
calculator.sub(10, 20)
  • import 키워드 사용
    • calculator라는 이름의 모듈 전체를 가져옴
    • 모듈명.함수() 형식으로 사용해야 함
    • 장점: 모듈 구조가 명확하게 보여서 이해하기 쉬움
    • 단점: 모듈명이 길 경우 코드가 길어짐

 

 

import calculator as cal

cal.add(10, 20)
cal.sub(10, 20)
  • import ~ as ~ 키워드 사용
    • calculator 모듈을 cal이라는 이름으로 축약해서 사용
    • 장점: 모듈명을 짧게 줄일 수 있어서 편리함
    • ex) matplotlib.pyplot as plt, pandas as pd처럼 많이 쓰임

 

 

from calculator import add, sub

add(10, 20)
sub(10, 20)
  • from ~ import ~ 키워드 사용
    • calculator 모듈에서 특정 함수만 가져옴
    • 장점: 필요한 기능만 불러와 코드가 짧고 간결해짐
    • 단점: 함수가 어디서 왔는지 명시가 안 되기 때문에 가독성이 떨어질 수 있음

 

 

  • 실습 코드 : 점수 계산 모듈
# 모듈 파일 (scores.py)
scores = []

def addScore(s):
    scores.append(s)

def getScores():
    return scores

def getTotalScore():
    total = 0
    for s in scores:
        total += s
    return total

def getAvgScore():
    avg = getTotalScore() / len(scores)
    return avg
# 실행 파일
import scores as sc

korScore = int(input('국어 점수 입력: '))
engScore = int(input('영어 점수 입력: '))
matScore = int(input('수학 점수 입력: '))

sc.addScore(korScore)
sc.addScore(engScore)
sc.addScore(matScore)

print(sc.getScores())         # [국어, 영어, 수학]
print(sc.getTotalScore())     # 총점
print(sc.getAvgScore())       # 평균

 

방법 사용법 장점 단점
import 모듈명 전체 모듈 사용 명확한 구조 이름 길면 불편
import 모듈명 as 별칭 축약형 사용 짧고 간결 약간 추상적일 수 있음
from 모듈명 import 기능 필요한 기능만 간단함 모듈 출처 불분명

개인적으로 as를 이용한 축약형을 많이 사용했다.

 

 

 

 

[나의 생각 정리]

  • 내장 함수와 사용자 정의 함수
    • 코드의 가독성유지보수성이 중요함
  • 가변 인자와 반환
    • 확장 가능한 함수 설계의 중요성을 느꼈음
  • 지역 변수와 전역 변수
    • 변수의 범위를 이해하고, 불필요한 전역 변수 사용을 줄여 코드의 안정성을 높여야 한다는 점을 배웠음

 

[적용점]

  • 문제 해결 시 함수 활용 극대화
    • 반복되는 코드를 함수로 분리, 필요한 인수와 반환값을 명확히 하여 모듈화 된 코드를 작성
  • 가변 인자와 기본 매개변수 적극 활용
    • 함수 호출 시 인수 개수가 유동적인 경우 *args를 사용해 코드의 유연성을 높일 수 있음
  • 전역 변수 최소화 및 지역 변수 활용
    • 변수의 사용 범위를 최대한 좁혀 예기치 않은 사이드 이펙트를 줄이고, 필요할 때만 global 키워드를 사용
  • 내장 함수의 적극 활용
    • 내장 함수들을 최대한 활용해 코드를 간결하고 효율적으로 작성

 

 

 

“이 글은 제로베이스 데이터 스쿨 주 3일반 강의 자료 일부를 발췌하여 작성되었습니다.”