[인공지능사관학교] Python (5)

Suhyeon Lee·2025년 6월 12일
post-thumbnail

함수

함수의 개념과 응용

함수(Function)

파이썬 함수는 크게 두 가지: 시스템 함수, 사용자 정의 함수
→ 시스템 함수: print(), input() 같은 함수
→ 이 챕터에서 학습하는 함수 == 사용자 정의 함수
★클래스에서 사용하는 메서드(method)와 이 챕터에서 학습하는 사용자 정의 함수는 거의 같은(99%) 개념★
(문법이 많이 호환됨)
★★★★★
※ 사용자 정의 함수는 def 키워드(예약어) 사용해 "정의"(선언)함※
※ 정의된 사용자 정의 함수는 "호출"하여 함수 정의부의 코드를 실행함※
★★★★★
→ "정의에 의해 만들어지고 호출에 의해 동작한다."

  • 소프트웨어에서 특정 동작을 수행하는 일정 코드 블럭
    • 특정 동작의 수행을 위해 코드와 명령어를 구분이 되는 이름(함수명, 예시: func1)으로 정의한 다음 하위에 종속 문장을 구성함으로써 함수를 정의함
    • 함수명을 호출할 때마다 종속 문장의 코드와 명령어가 실행됨
    • 설계의 방향에 따라 명령어의 실행 결과를 호출한 곳에 반환(return)하기도 함
  • 파이썬에서는 함수나 메서드를 정의할 때 definition을 줄인 키워드 def를 사용
def func(num1, num2):
# 'func'이라는 이름의 함수를 정의
# 함수명: func
	return num1 ** num2
  • 함수는 정의를 하는 것만으로는 동작하지 않고, 반드시 "호출"을 해야 함수 안의 종속 문장을 수행함 ★
# 함수 정의 예
def func1(매개변수1, 매개변수2, ...): # 함수 정의
	종속 문장 1
    종속 문장 2
    종속 문장 3

# 함수 호출 예
func1(인수1, 인수2, ...) 
# 함수 호출 사례 1: 반환값이 없을 때
sum = func1(인수1, 인수2, ...)
# 함수 호출 사례 2: 반환값이 있을 때
  • 예시
def func1(p_num1, p_num2): # 함수 정의
	print(p_num1 + p_num2)
	print(p_num1 * p_num2)
	print(p_num1 / p_num2)

# p_num1, p_num2: 매개변수(parameter)

func1(num1, num2)
# 함수 호출 사례 1: 반환값이 없을 때
sum = func1(num1, num2)
# 함수 호출 사례 2: 반환값이 있을 때

# num1, num2: 인수/인자(argument)
  • 한 번 정의해 놓으면 여러 번 호출할 수 있음

Class, Object, Instance

  • Class
    • 객체를 만들어 내기 위한 설계도, 틀
    • 연관되어 있는 변수와 메서드의 집합
  • Object
    • 소프트웨어 세계에 구현할 대상
    • 클래스에 선언된 모양 그대로 생성된 실체
    • 특징
      • '클래스의 인스턴스'라고도 부름
      • 모든 인스턴스를 대표하는 포괄적인 의미
      • oop의 관점으로 "클래스의 타입으로 선언되었을 때" object(객체)라 부름
  • Instance
    • 설계도를 바탕으로 소프트웨어 세계에 구현된 구체적인 실체
      • 객체를 소프트웨어에 실체화하면 그걸 '인스턴스'라 부름
    • 실체화된 인스턴스는 메모리에 할당됨
    • 특징
      • 인스턴스는 객체에 포함된다고 볼 수 있음
      • oop의 관점에서 "객체가 메모리에 할당되어 실제 사용될 때" 인스턴스라고 부름
      • 추상적인 개념 또는 명세와 구체적인 객체 사이의 "관계"에 초점을 맞출 때 사용
  • 인스턴스라는 용어는 반드시 클래스와 객체 사이의 관계로 한정지어 사용할 필요는 없음 → 어떤 원본(추상적인 개념)으로부터 '생성된 복제본'을 의미하기 때문
    • 객체는 클래스의 인스턴스다.
    • 객체 간의 링크는 클래스 간의 연관 관계의 인스턴스다.
    • 실행 프로세스는 프로그램의 인스턴스다.

예제 1

result, temp = 0, 0
result = int(input("수 입력:"))
while True:
    temp = int(result % 10)
    result = int(result / 10)
    print(temp, end='')
    if not result:
        break
print("\n프로그램 종료")

def reverseCode():
    result, temp = 0, 0
    result = int(input("수 입력:"))
    while True:
        temp = int(result % 10)
        result = int(result / 10)
        print(temp, end='')
        if not result:
            break
print("\n프로그램 시작")
reverseCode()
print("\n프로그램 종료")

파이썬은 '인터프리터 방식' → 한 줄씩 번역

함수를 선언한 부분: 실행은 이루어지지 않고 '실행이 일어날 수 있는 부분이 존재한다'고 인식만 함
line 11을 읽고 제어가 1로 뛰어 넘어가서 실행됨: 함수 호출
line 1~9 → 번역, 인식 동시에
line 10~12 → 번역, 인식, 살행 동시에

예제 2

sel = 0
sel = int(input("음료 선택\n1. 콜라\n2. 핫6\n3. 포카리\n입력:"))
if sel == 1:
    print("콜라 등장")
elif sel == 2:
    print("핫6 등장")
elif sel == 3:
    print("포카리 등장")
else:
    print("만들어 드세요^^")

if sel >= 1 and sel <= 3:
    print("맛있게 드세요^^")

def sel_machine():
    sel = 0
    sel = int(input("음료 선택\n1. 콜라\n2. 핫6\n3. 포카리\n입력:"))
    if sel == 1:
        print("콜라 등장")
    elif sel == 2:
        print("핫6 등장")
    elif sel == 3:
        print("포카리 등장")
    else:
        print("만들어 드세요^^")

    if sel >= 1 and sel <= 3:
        print("맛있게 드세요^^")
sel_machine()

예제 3

def calc():
    result = 0
    su1, op, su2 = int(input("숫자:")), input("부호:"), int(input("숫자:"))
    result = su1 + su2
    print(su1, '+', su2, '=', result)
calc()

def calc():
    result = 0
    su1, op, su2 = int(input("숫자:")), input("부호:"), int(input("숫자:"))
    if op == '+':
        result = su1 + su2
    elif op == '-':
        result = su1 - su2
    elif op == '*':
        result = su1 * su2
    elif op == '/':
        result = su1 / su2
    print(su1, op, su2, '=', result)
calc()

매개변수와 인수

def calc(su1, op, su2): # 매개변수 → A
result = 0

result = su1 + su2
print(su1, '+', su2, '=', result)

su1, op, su2 = int(input("숫자:")), input("부호:"), int(input("숫자:"))
calc(su1, op, su2) # 인수 → B

  • 주인집 B 바구니의 변수(▶인수)머슴집 A 바구니의 변수(▶매개변수)에 복사
  • 위 예제에서 인수와 매개변수의 이름은 같지만 역할은 다름
    • 엄격하게 다른 변수임을 인식해야 함
  • 매개변수의 수는 해당 함수의 기능과 동작에 따라 달라짐
  • 앞선 예시와 비교했을 때 함수의 호출과 설계가 다름!
    • 함수의 호출부 괄호 안에 들어가 있는 인수의 값을 "복사"해 함수의 선언부 괄호 안에 들어가 있는 매개변수에 전달
      • '복사의 방식'으로 주는 게 포인트!
        → 할당되는 것과 유사
        (할당은 객체의 참조를 복사하는 것이고, 복사는 객체의 실제 값을 복사하는 것)

예제 1

# 함수 정의 및 호출, 반환의 가장 전형적인 사례
def cal(su1, op, su2): # 매개변수
    result22 = 0
    result22 = su1 + su2
    print("cal 실행")
    return result22

su1, op, su2 = int(input("숫자:")), input("부호:"), int(input("숫자:"))
result = cal(su1, op, su2) # 인수
print(su1, '+', su2, '=', result)
print("다음 문장 실행")

  • 인수를 매개변수에 전달하고 return 문을 통해 결과를 반환 → 함수 동작 방식의 전형

예제 2

def showAvrg(a, b, c):
    print("{}와 {}의 평균".format(a, b))
    print("값은 {}입니다.".format(round(c, 1)))
def avrg(j, k):
    total = j + k
    ff = total / 2
    return ff
i = 2
j = 3
f = avrg(i, j)
showAvrg(i, j, f)
print("다음 문장 실행")

파이썬 함수 명명 규칙(묵시적)
함수명, 메서드명 시작은 소문자로
클래스명 시작은 대문자로
카멜 표기법: JAVA → showAvrg
스네이크 표기법: C, C++ → sel_machine
파이썬은 표기법에 대한 묵시적 규정은 없어서 각 회사별로 알잘딱깔센 하면 됨

예제 3

  • 아래 코드의 실행 결과를 먼저 예상해 본 후에 실행하세요.
def func2(a,b):
    a += 5
    b *= 10
    print("func2: a={}, b={}".format(a, b))
def func1():
    a = 5
    b = 10
    func2(a, b)
    print("func1: a={}, b={}".format(a, b))
func1()

func2: a=10, b=100
func1: a=5, b=10

예제 4

num1 = input("수 입력:")
num2 = int(input("수 입력:"))
print(type(num1))
print(type(num2))
  • 위의 내용을 토대로 사용자 만의 myType 함수를 만드시오.
def myType(n):
    if type(n) == int:
        return f"{n}: 정수 형태입니다."
    elif type(n) == str:
        return f"{n}: 문자(열) 형태입니다."
    else:
        return f"{n}: 정수 형태도 문자(열) 형태도 아닙니다."
num1 = input("수 입력:")
num2 = int(input("수 입력:"))
num3 = float(input("수 입력:"))
print(myType(num1))
print(myType(num2))
print(myType(num3))
# 해답
def myType(su):
    if type(su) == int:
        return str(su) + ":정수(int)형태입니다."
    elif type(su) == str:
        return su + ":문자(str)형태입니다."
    else:
        return "어떤것인지 모르겠습니다"
num1 = input("수 입력:")
num2 = int(input("수 입력:"))
num3 = float(input("수 입력:"))
print(myType(num1))
print(myType(num2))
print(myType(num3))

→ 해답 line 4에서 str(su)로 쓰는 이유:
파이썬에서 숫자와 문자열을 직접 + 연산자로 더하면 TypeError 오류가 발생

파이썬에서 + 연산자는 숫자와 문자열에 서로 다른 방식으로 적용되기 때문
(숫자의 경우 덧셈을 수행하고, 문자열의 경우 문자열을 연결)
따라서 숫자를 문자열로 변환한 후 + 연산을 수행해야 함
숫자와 문자열을 직접 연산하기 위해서는 str() 함수를 사용하여 형 변환하는 것이 일반적!

변수(Scoping Rule 스코핑 룰)

  • 지역 변수와 전역 변수

    • 지역 변수: 한정된 지역(Local)에서만 사용되는 변수
    • 전역 변수: 프로그램 전체(Global)에서 사용되는 변수
  • 지역 변수

def func1():
    a = 100 # 지역 변수
    print("func1의 a: %d" %a)

def func2():
    a = 200 # 지역 변수
    print("func2의 a: %d" %a)

func1()
func2()

func1의 a: 100
func2의 a: 200

  • 전역 변수
def func1():
    print("func1의 a: %d" %a)

def func2():
    print("func2의 a: %d" %a)

a = 200 # 전역 변수

func1()
func2()

func1의 a: 200
func2의 a: 200

Python Scoping Rule
변수의 접근 범위(scope)를 결정하는 규칙
어떤 변수를 어디에서 사용할 수 있는지, 그리고 그 변수가 어떤 다른 변수와 관련되었는지 정함
주요 스코핑 규칙으로는 LEGB rule이 있음

  • LEGB 룰
    • L (Local): 함수 내에서 정의된 변수 (지역 변수)를 먼저 찾기
    • E (Enclosing function locals): 함수 내에 또 다른 함수가 있고, 그 내부 함수에서 변수를 찾을 때, 상위 함수에 정의된 변수를 찾기
    • G (Global): 프로그램의 최상위 수준에서 정의된 변수 (전역 변수)를 찾기
    • B (Built-in): 파이썬에 내장된 함수나 변수를 찾기
# 전역 변수
x = 10

def outer_func():
    # 지역 변수 (outer_func)
    x = 5

    def inner_func():
        # 지역 변수 (inner_func)
        x = 3
        print(x)  # 3 (inner_func의 지역 변수 x 출력)

    inner_func()
    print(x)  # 5 (outer_func의 지역 변수 x 출력)

outer_func()
print(x)  # 10 (전역 변수 x 출력)

inner_func() 내에서 x를 사용하면, 우선적으로 inner_func()의 지역 변수 x가 사용되고, 없으면 outer_func()의 지역 변수 x를 사용하고, 없으면 전역 변수 x를 사용함

예제 1

def func1():
    a = 123 # 지역 변수
    print("func1의 a: %d" %a)

def func2():
    print("func2의 a: %d" %a)

a = 200 # 전역 변수
func1()
func2()

func1의 a: 123
func2의 a: 200

예제 2

def func1():
    global a # 함수(머슴)의 영역에서 전역 변수를 선언한 경우
    a = 1222
    print("func1의 a: %d" %a)

def func2():
    print("func2의 a: %d" %a)

a = 200 # 전역 변수
func1()
func2()

func1의 a: 1222
func2의 a: 1222

전역 변수 수행 시점을 이해해야 함!
→ 마지막으로 지정(선언)된 전역변수를 사용함

변수의 사용 범위 알아보기

예제 3

def display():
    num = 10
    print("10까지의 합:", sumFunc(num))
def sumFunc(num):
    sum = 0
    for i in range(num+1):
        sum += i
    return sum
display()
  • 전역 변수는 되도록 쓰지 않는 게 maintenance에 좋음!

    • 매우 신중하게 사용해야 함
  • 전역 변수를 되도록 안 쓰는 이유를 보여주는 예제

num = 10
sum = 0
def display():
    sumFunc(num)
    print("10까지의 합:", sum)
def sumFunc(num):
    global sum
    for i in range(num+1):
        sum += i
display()

Default Parameter

  • 함수를 선언할 때 매개변수에 할당 문법을 부여
    • 인수가 들어오지 않았을 때 할당된 값으로 대체
def sum_func(x1, x2, x3 = 100):
    result = 0
    result = x1 + x2 + x3
    return result
def display():
    Sum = 0
    a, b, c = 10, 20, 30
    Sum = sum_func(a, b)
    print("매개변수 2개 함수 호출:", Sum)
    Sum = sum_func(a, b, c)
    print("매개변수 3개 함수 호출:", Sum)
display()

예제

def alba(day = 30, time = 8, won = 8500):
    result = day * time * won
    return result
def display():
    num = int(input("1. 기본급\n2. 일한 날짜 입력\n"))
    if num == 1:
        result = alba()
    elif num == 2:
        day = int(input("일한 날짜 입력(몇 일):"))
        result = alba(day)
    print("당신의 급여: {}원 입니다.".format(result))
display()

Arbitrary Argument List(가변 인수 리스트)

def sum_func(*par):
    result = 0
    print("type:", type(par))
    print("par:", par)
    for num in par:
        result = result + num
        print("num: %d" %num)
    return result
Sum = 0
Sum = sum_func(10, 20)
print("매개변수 2개 함수: %d" %Sum)
Sum = sum_func(10, 20, 30, 40)
print("매개변수 4개 함수: %d" %Sum)
  • *par

    • par라는 매개변수가 유동적 → 매개변수명 앞에 별(/*, asterisk)을 붙임: 튜플
  • 매개변수 앞에 별이 두 개: 딕셔너리 형식으로 여러 가지 데이터를 인수로부터 받겠다는 의미

    • 인수를 입력할 때 key = value 형식을 지켜야 함!
      • =를 사용해야 함(':' 쓰면 에러)

예제 1

def dic_func(**par):
    print("type(par)", type(par))
    for k in par.keys():
        print("{}: {}명입니다.".format(k, par[k]))
dic_func(똭뚝뽹 = 123, 꿔익꿔익 = 8, test = "테스뚜")

예제 2

def change(a, b, c):
    return a+10, b+20, c+30

a, b, c = change(10, 20, 30) # 튜플의 언패킹 개념
d = change(10, 20, 30)
print("a, b, c:", a, b, c)
print("d: {}, type: {}".format(d, type(d)))
  • 언패킹(unpacking)
    • 묶여 있는 객체를 여러 개의 값으로 풀어주는 개념
      (여러 개의 객체를 포함하고 있는 하나의 객체를 풀어줌)
    • cf. 패킹: 매개변수 이름 앞에 *을 붙여 위치인자로 보낸 모든 객체들을 하나의 객체로 관리 ↔ 언패킹: 함수에서 unpacking을 할때는, 매개변수에서 *을 붙이는게 아니라 인자 앞에 *을 붙여서 사용
tp1 = 20,40,60
print(tp1)
num1, num2, num3 = tp1
# tp1 이라는 튜플에서
# 변수 num1, num2, num3 세 개의 변수로
# 요소를 언패킹한다. 
print( num1, num2, num3)

profile
2 B R 0 2 B

0개의 댓글