스터디/파이썬 스터디 강의자료

[1팀/한규림] 5차시 파이썬 스터디 - 함수

onegyul 2023. 4. 6. 14:36

5차시_함수_강의안.pdf
0.62MB
5차시_함수_과제.pdf
0.13MB

5차시 강의 주제는 함수입니다.

01. 함수 기초

여러 명이 프로그램을 함께 개발할 때, 우리는 일반적으로 팀원들이 각자 해야 할 부분을 나눠서 코딩한 다음 합치는 방식으로 한다. 그렇다면 프로그램을 만들 때 작성해야 하는 부분을 나누는 방법에는 어떤 것이 있을까?

파이썬에서는 이를 위해 함수, 객체, 모듈을 제공한다. 이번주에는 함수의 개념에 대해 배우고, 나중에 객체와 모듈(8,9주차)에 대한 개념을 배워보자.

1) 함수의 개념과 장점

  • 함수 : ‘어떤 일을 수행하는 코드의 덩어리, 또는 코드의 묶음’
  • 함수의 장점
    • 필요할 때마다 호출 가능 : 반복적으로 수행해야 하는 업무를 할 때!
    • 논리적인 단위로 분할 가능 : 간단히 도형을 계산하는 프로그램에서도 곱셈을 하는 코드, 덧셈을 하는 코드, 나눗셈을 하는 코드 등으로 분할이 가능하다!
    • 코드의 캡슐화 : 캡슐화는 함수의 인터페이스만 잘 정의(코드에 입력되는 input값과 output값을 명확히 하는 것)하면 다른 사람이 자신의 코드를 쉽게 가져다 사용할 수 있는 특징이 있음.

2) 함수의 선언

  • def 함수 이름 (매개변수 #1 …): 명령문1 명령문2 return <반환값>
  • def : ‘definition’의 줄임말, ‘함수 정의를 시작한다’는 의미
  • 함수 이름 : 개발자 마음대로 지정하지만 일반적으로 규칙을 사용함.
    • 소문자로 입력한다.
    • 띄어쓰기를 할 경우에 _ 기호를 사용한다.
    • 작업을 나타내기 위해 동사와 명사를 함께 사용하는 경우가 많다.
    • 외부에 공개하는 함수일 경우 줄임말을 사용하지 않고 짧고 명료한 이름으로 정한다.
  • 매개변수(parameter) : 함수에서 입력값으로 사용하는 변수를 의미. 1개 이상 값을 적을 수 있음.
  • 명령문 : 들여쓰기한 후 코드 입력하기! if, for문 등의 제어문을 사용하거나, 고급 프로그래밍 기법으로 함수 안에 함수를 사용하기도 함.
def calculate_rectangle_area(x, y):
		return x * y
  • 함수 이름은 calculate_rectangle_area 이다.
  • x, y 2개의 매개변수를 사용하고 있다.
  • x, y를 곱한 값을 반환하는 함수이다. (return : 값을 반환한다는 뜻)

3) 함수의 실행 순서

def calculate_rectangle_area(x, y):
		return x * y

rectangle_x = 10
rectangle_y = 20
print("사각형 x의 길이:", rectangle_x)
print("사각형 y의 길이:", rectangle_y)

# 넓이를 구하는 함수 호출
print("사각형의 넓이:", calculate_rectangle_area(rectangle_x, rectangle_y))

# 출력 결과
사각형 x의 길이: 10
사각형 y의 길이: 20
사각형의 넓이: 200
  • 함수가 정의된 def 부분은 실행되지 않음. 단지 정의만 하는 것.
    실제로는 해당 코드를 메모리에 업로드해서 다른 코드를 호출해 사용할 수 있도록 준비 과정을 거침.
  • 함수가 수행해야 하는 명령 실행하기
    함수 호출 후 변수에 할당된 값이 함수에 입력값이 되고 코드 return x * y에 의해 반환값 200이 출력됨.

4) 프로그래밍의 함수와 수학의 함수

  • f(x) = 2x+7, g(x) = x² 이고 x = 2 일 때 f(x) + g(x) + f(g(x)) + g(f(x)) 의 값은?
    f(2) = 11, g(2) = 4, f(g(x)) = 15, g(f(x)) = 121 → 11 + 4 + 15 + 121 = 151
def f(x):
		return 2 * x + 7
def g(x):
		return x ** 2
x = 2
print(f(x) + g(x) + f(g(x)) + g(f(x)))  # 151 출력

매개변수(parameter)와 인수(argument)

def f(x):
		 return 2 * x + 7

print(f(2))  # 11 출력

x를 매개변수라고 하고, 인수는 실제 매개변수에 대입되는 값을 뜻하므로 2가 인수에 해당함.

5) 함수의 형태

  • 매개변수와 반환값의 유무에 따라 네 가지 형태로 구분할 수 있음.
    • 반환값x, 매개변수x : 함수 내부 명령문만 수행
    • 반환값x, 매개변수o : 매개변수를 사용하여 명령문만 수행
    • 반환값o, 매개변수x : 매개변수 없이 명령문을 수행한 후 결과값 반환
    • 반환값o, 매개변수o : 배개변수를 사용하여 명령문을 수행한 후 결과값 반환
def a_rectangle_area():  # 매개변수 x, 반환값 x
		print(5 * 7)
def b_rectangle_area(x, y):  # 매개변수 o, 반환값 x
		print(x * y)
def c_rectangle_area():  # 매개변수 x, 반환값 o
		return(5 * 7)
def d_rectangle_area(x, y):  # 매개변수 o, 반환값 o
		return(x * y)

a_rectangle_area()
b_rectangle_area(5, 7)
print(c_rectangle_area())
print(d_rectangle_area(5, 7))

# 출력결과
35
35
35
35
  • 매개변수 x, 반환값 x : 함수 자체는 none값을 가지지만 print(5 *7)로 인해 35 출력됨.
  • 매개변수 o, 반환값 x : b_rectangle_area(5, 7)이라고 실행시켜야 35가 출력되는 것이지 b_rectangle_area(5, 7) 자체가 35로 치환되는 것은 아님. 반환이 없으면 해당 함수는 none으로 치환.
  • 매개변수 x, 반환값 o / 매개변수 o, 반환값 o : 함수 안에서 print( ) 함수를 수행시키는 것이 아닌 함수를 호출할 때 print( ) 함수를 이용함. return문으로 인해 35로 치환되는 것. return이 있는 경우(함수의 반환값이 있는 경우) 그 함수를 호출하는 곳에서 함수의 반환값을 변수에 할당하여 사용하는 것이 가능함.

02. 함수 심화

1) 함수의 호출 방식

def f(x):
		y = x
		x = 5
		return y * y

x = 3
print(f(x))
print(x)

# 출력결과
9
3
  •  함수가 변수를 호출하는 방식
    • 값에 의한 호출(call by value) : 함수에 인수를 넘길 때 값만 넘김, 함수 내부의 인수값 변경 시 호출된 변수에 영향을 주지 않음
    • 참조 호출(call by reference) : 함수에 인수를 넘길 때 메모리 주소를 넘김, 함수 내부의 인수값 변경 시 호출된 변수값도 변경됨
  • 객체의 주소가 함수로 넘어간다는 뜻의 ‘객체 호출’(call by object reference) 방식을 사용함.
    객체의 주소를 함수로 넘기기 때문에 전달된 객체의 값에 변경이 있을 경우 영향이 있음.
def spam(eggs):
		eggs.append(1)  # 기존 객체의 주소값에 [1] 추가
		eggs = [2, 3]  # 새로운 객체 생성

ham = [0]
spam(ham)
print(ham)

# 출력 결과
[0, 1]

2) 변수의 사용 범위

  • scoping rule : 변수가 코드에서 사용되는 범위
    • 지역 변수(local variable) : 함수 내부에서만 사용
    • 전역 변수(global variable) : 프로그램 전체에서 사용
def test(t):
		print(x)
		t = 20
		print("In Function:", t)

x = 10
test(x)
print("In Main:", x)
print("In Main:", t)

# 출력 결과
10
In Function: 20
In Main: 10
Traceback (most recent call last):
		File "scoping_rule.py", line 9, in <module>
				print("In Main:", t)
NameError: name 't' is not defined
def f():
		s = "I love London!"
		print(s)

s = "I love Paris"
f()
print(s)

# 출력 결과
I love London!
I love Paris!
def f():
		global s
		s = "I love London!"
		print(s)

s = "I love Paris!"
f()
print(s)

# 출력 결과
I love London!
I love London!
def caculate(x, y):
		total = x + y
		print("In Function")
		print("a:", str(a), "b:", str(b), "a + b:", str(a + b), "total:", str(total))
		return total

a = 5
b = 7
total = 0
print("In Program -1")
print("a:", str(a), "b:", str(b), "a + b:", str(a + b))

sum = calculate(a, b)
print("After Calculation")
print("Total:", str(total), "Sum:", str(sum))

3) 재귀 함수

  • 재귀 함수 : 자기 자신을 다시 호출하는 함수
    재귀적이라는 표현은 자신을 이용해 다른 것을 정의한다는 뜻임.
    재귀 함수는 수학의 점화식과 같은 형태.
def factorial(n):
		if n == 1:
				return 1
		else:
				return n * factorial(n - 1)

print(factorial(int(input("Input Number for Factorial Calculation:"))))

# 출력 결과
Input Number for Factorial Calculation: 5
120
  • factorial( ) 함수는 n이라는 변수를 입력 매개변수로 넘겨받은 후 n == 1이 아닐 때까지 입력된 n과 n-1을 입력값으로 다시 factorial( ) 함수를 호출하여 반환된 값과 곱함.
  • factorial을 구하는 함수는 for문이나 while문으로도 표현이 가능함. 재귀 함수의 기본 구조가 종료 조건, 단계별 반환으로 구성되어 있으므로 크게 변경 없이 사용이 가능함. 반복문에서도 마찬가지로 종료 조건과 반복문마다 동일한 연산이 진행되기 때문.
  • 재귀 함수는 고급 프로그래머로 갈수록 재귀적으로 작성된 프로그램을 자주 접하게 되므로 개념적으로 잘 이해하고 있어야 함.

03. 함수의 인수

1) 키워드 인수

  • 함수의 인터페이스에서 지정한 매개변수의 변수명을 사용하여 함수의 인수를 지정하는 방법
def print_something(my_name, your_name):
		print("Hello {0}, My name is {1}".format(your_name, my_name))

print_something("Freshman","DSOB")
print_something(your_name = "DSOB", my_name = "Freshman")

# 출력 결과
Hello DSOB, My name is Freshman
Hello DSOB, My name is Freshman
  • print_something( ) 함수는 (my_name, your_name)이라는 입력 인터페이스를 가짐.
  • 두 함수에 대한 2가지 호출 코드의 실행 결과가 동일하게 출력됨.

2) 디폴트 인수

  • 별도의 인수값이 입력되지 않을 때 인터페이스 선언에서 지정한 초깃값을 사용하는 방법
  • 매개변수에 기본값을 지정하여 사용하고, 아무런 값도 인수로 넘어가지 않을 때 지정된 기본값을 사용하는 방식
def print_something_2(my_name, your_name = "DSOB"):
    print("Hello {0}, My name is {1}".format(your_name, my_name))

print_something_2("Freshman", "DSOB")
print_something_2("Freshman")

# 출력 결과
Hello DSOB, My name is Freshman
Hello DSOB, My name is Freshman
  • 디폴트 인수를 사용할 때 보통 함수를 사용하는 사람이 초깃값을 입력해주어야 할 때가 있음.

3) 가변 인수

  • 함수의 인터페이스에서 지정한 변수 이외의 추가 변수를 함수에 입력할 수 있도록 지원하는 방법
def asterisk_test(a, b, *args):
    return a + b + sum(args)

print(asterisk_test(1, 2, 3, 4, 5))

# 출력 결과
15
  • *args : 가변 인수
def asterisk_test(a, b, *args):
    print(args)

print(asterisk_test(1, 2, 3, 4, 5))

# 출력 결과
(3, 4, 5)
None
  • 괄호로 묶여 출력되는 자료형을 튜플(tuple) 자료형이라고 함.
    리스트 자료형처럼 인덱스로 접근할 수 있는 자료형이라고만 알아두면 됨.
  • 가변인수 *는 반드시 일반적인 키워드 인수에 대한 선언이 모두 끝난 후 마지막에 선언되어야 함.
  • 튜플 형태로 함수 안에서 사용되므로 인덱스를 사용하여 args[0], args[1] 등의 형태로 변수에 접근할 수 있음.
def asterisk_test_2(*args):
    x, y, *z = args  # 언패킹
    return x, y, z

print(asterisk_test_2(3, 4, 5))

# 출력 결과
(3, 4, [5])
  • 입력받은 가변 인수의 개수를 정확히 안다면 언패킹을 할 수 있음.
    만약 *z가 아닌 상태로 asterisk_test_2(3, 4, 5, 10, 20)으로 변경하여 실행한다면 오류가 발생함.
    언패킹의 개수가 맞지 않기 때문.
def asterisk_test_2(*args):
    x, y, *z = args
    return x, y, z

print(asterisk_test_2(3, 4, 5, 10, 20))

# 출력 결과
(3, 4, [5, 10, 20])

4) 키워드 가변 인수

  • 매개변수의 이름을 따로 지정하지 않고 입력하는 방법
  • 가변 인수는 변수의 순서대로 튜플 형태로 저장됨.
    사용은 간단하지만 변수의 이름을 지정할 수 없다는 단점이 있음.
    이를 보완한 것이 키워드 가변 인수 이다.
    매개변수의 이름을 따로 지정하지 않고 입력하는 방법으로 *을 2개 사용하여 함수의 매개변수를 표시한다.
  • 입력된 값은 튜플 자료형이 아닌 딕셔너리 자료형으로 사용할 수 있다.
def kwargs_test(**kwargs):
    print(kwargs)
    print("First value is {first}".format(**kwargs))
    print("Second value is {second}".format(**kwargs))
    print("Third value is {third}".format(**kwargs))

kwargs_test(first=3, second=4, third=5)

# 출력 결과
{'first': 3, 'second': 4, 'third': 5}
First value is 3
Second value is 4
Third value is 5

04. 좋은 코드를 작성하는 방법

1) 좋은 코드의 의미

  • 프로그래밍은 팀플레이다. 좋은 프로그래밍을 위해 규칙이 있어야한다.
  • 컴퓨터가 이해할 수 있는 코드는 어느 정도 실력이 되면 만들 수 있지만, 좋은 프로그래머가 되기 위해서는 사람이 이해할 수 있는 프로그램 코드를 만들어야 한다.
    다른 사람이 내가 작성한 코드를 굉장히 쉽게 이해할 수 있도록 프로그램을 작성해야 한다.

2) 코딩 규칙

  • 들여쓰기는 4스페이스
  • 한 줄은 최대 79자까지
  • 불필요한 공백은 없애기
  • = 연산자는 1칸 이상 띄우지 않기
  • 주석은 항상 갱신하고 불필요한 주석을 삭제하기
  • 소문자 l, 대문자 O, 대문자 I는 사용을 금함. (구분이 어려움)
  • 함수명은 소문자로 구성하고, 필요시 밑줄로 구분하기

3) 함수 개발 가이드라인

  • 함수 이름
    • 함수 내용은 가능하면 짧게 작성할 것 (줄 수를 줄일 것)
    • 함수 이름에 함수의 역할과 의도를 명확히 드러낼 것
  • 함수의 역할
    • 하나의 함수에는 유사한 역할을 하는 코드만 포함시켜야 함 함수는 한 가지 역할을 명확히 해야 함
  • 함수를 만들어야 하는 경우
    • 공통으로 사용되는 코드를 함수로 변환
    • 복잡한 로직이 사용되었을 때 식별 가능한 이름의 함수로 변환
  • hello1.py, hello2.py, math1.py, math2.py를 참고하자.