https://book.naver.com/bookdb/book_detail.nhn?bid=16268369
으뜸 파이썬과 함께 공부하는 포스트입니다.

실행 결과

함수에 특정한 작업을 위임하기 위하여 정확한 인자를 넣어주는 것도 필요하지만 가끔씩은 위와 같은 에러를 예방하고 좀 더 유연성 있는 작업을 위해 디폴트(기본 값) 값을 사용하는 것이 편리할 때가 있다.
이때 사용하는 것이 디폴트 인자인데, 매개변수에 n = 1과 같이 디폴트 값을 할당해 주면 된다. 할당을 하고 나면 프로그램은 인자가 없이 호출해도 디폴트 값 1을 매개변수 n에 전달하므로 한 줄의 별표 라인이 정상적으로 된다.

실행 결과

물론 print_star() 함수 호출시 인자 2를 입력하게 되면 디폴트 값 1을 취하지 않고 인자 값 2를 n으로 가진다. 따라서 이 경우 2개의 별표 줄을 출력한다.

실행 결과

이제 두개의 매개변수를 사용하는 div()라는 함수를 정의해 보자. 이 때, 두번째 매개변수에만 2를 할당해보자.

실행 결과

위와 같이 함수 호출시 div(4)와 같이 두번째 인자를 생략하면 함수 내부에서 디폴트 매개변수 값으로 2를 취하여 4/2 = 2.0의 결과를 반환하는 것을 확인할 수 있다.
그러면 첫번째 매개변수에 2를 할당하고 두번째 매개변수를 생략하면 어떻게 될까?

실행 결과

에러가 발생한다. 이유는 함수에서 div(4)를 호출하면 4라는 값을 디폴트 매개변수인 a에 할당할지 디폴트 값을 가지지 않는 b에 할당해야 할지 인터프리터가 정확하게 결정하기 어려운 모호한 상황에 빠지기 때문이다. 따라서 디폴트 매개변수는 전체 변수에 대해 모두 할당하거나 매개변수의 출현 순서상 뒤에 있는 변수부터 할당하여야 한다.
다음은 모든 매개변수 a,b에 디폴트 값을 할당한 프로그램이다.

실행 결과

이 프로그램에서 각각 div(), div(4), div(6,3)은 함수 호출문, div(1,2) , div(4,2), div(6,3) 는 실제 수행시 넘겨지는 인자, 반환값은 0.5, 2.0, 2.0이다.
키워드 인자는 함수를 호출할 때 인자의 값만을 전달하는 것이 아니라 그 인자의 이름을 함께 명시하여 전달하는 방식이다. 예를 하나 들어보겠다.

실행 결과

위 프로그램과 같이 2차 방정식의 근의 공식에서 a,b,c 게수는 매우 중요하다. 함수의 내부에서는 입력되는 인자의 순서가 a,b,c와 같이 들어올 때 a는 2차항의 계수이고 b는 1차항의 계수, c는 상수항의 계수라고 가정하고 방정식의 근을 구한다.
이와 같은 파이썬의 기본 인자 전달 방식을 위치 인자 방식이라고 한다. 즉, 인자의 순서에 따른 전달방식이라는 뜻이다.
그런데 함수를 호출하는 입장에서는 get_root(1, 2, -8)과 같이 사용하여 호출하므로, 각각의 인자가 가지는 순서와 의미를 정확히 알기 힘들 것이다. 즉 인자에서 -8이 상수항 c의 값이라는 것이 명확하지 않다.
이 때문에 이 순서를 잘못 이해하여 상수항인 -8을 제일 먼저 넣고 1차항의 계수 2를 두번째로 넣고, 2차항의 계수를 제일 뒤에 넣어 get_root(-8, 2, 1)과 같이 호출하면 -8x^2 + 2x + 1 방정식의 근을 구하게 될 것이며, 원하는 값과 전혀 다른 결과가 출력될 것이다.
실행 결과

따라서 이 a,b,c라는 매개변수를 키워드로 하여 이 키워드에 각각 값을 할당하게 된다면 보다 이해하기 쉬운 안전한 프로그램이 될 것이다.
이와 같이 키워드를 인자아 함께 전달하는 방식을 키워드 인자를 이용한 함수 호출이라고 한다. 이제 이 프로그램을 다음과 같이 키워드와 인자를 등호로 묶어서 호출해 보자.
result1, result2 = get_root(a = 1, b = 2, c = -8)
실행 결과

함수 호출시 a 값을 1, b 값을 2, c 값을 -8로 명시하여 호출하였으므로 프로그램의 의미도 명확해졌으며 오류의 가능성도 줄어들었다. 그리고 다음과 같이 a,b,c의 순서를 어디에 두더라도 그 결과는 동일하다.
result1, result2 = get_root(a = 1, c = -8, b = 2)
또는
result1, result2 = get_root(c = -8, b = 2, a = 1)
실행 결과

그렇다면 키워드 인자와 위치 인자를 섞어서 사용하면 어떻게 될까?
b와 c는 키워드 인자를, a는 위치 인자를 사용해보았다.

키워드 인자 뒤에 위치 인자를 사용할 수 없다는 에러 메시지를 출력한다.
이제 키워드 인자를 이용하여 문제를 해결해보자.
다음과 같이 성(last name)과 이름(first name), 존칭(honorifics)을 매개변수로 받아서 출력하는 함수 print_name이 있다.
def print_name(honorifics, first_name, last_name):
''' 키워드 인자를 이용한 출력용 프로그램 '''
print(honorifics, first_name, last_name)
a) 다음과 같은 함수 호출의 결과는 무엇인가?
print_name(first_name = 'Gildong', last_name = 'Hong', honorifics = 'Dr.')
실행 결과

b) 다음과 같은 함수 호출의 결과는 무엇인가?
print_name('Gildong', 'Hong', 'Dr.')
실행 결과

보다시피 위의 코드는 각각 Dr. Gildong Hong, Gildong Hong Dr. 가 출력되었는데 첫번째 코드가 정답이다.
두번째 코드와 같이 쓰려면 문법에 맞춰서 순서대로 쓰는것이 필요하고, 그것이 아니라면 첫번째 코드를 사용하는 것이 편하다.
앞서 살펴본 내용은 모두 함수 호출 시 인자 개수가 고정된 경우의 예이다. 하지만 인자의 개수를 미리 알지 못하는 경우에는 어떨까?
예를 들어 사람의 이름을 인자로 받아서 인사말을 출력하는 프로그램 작성시 한사람의 이름이 들어오게 되면 다음과 같이 출력하면 된다.

실행 결과

위 함수는 하나의 매개변수를 가지므로 한 사람의 이름을 인자로 받아 출력문에 전달하면 된다.
하지만 두 명의 이름을 입력받아 인사를 출력하려 할 경우 다음과 같이 두개의 매개변수를 가지는 프로그램이 필요하다.

실행 결과

이런 프로그램의 문제점은 다수의 이름이 들어오는 모든 경우에 대해 함수를 만들어야 하기 때문에 중복되는 기능의 함수를 너무 많이 만들어야 한다는 점이다. 그리고 수백명의 이름이 인자로 들어온다면 사실상 문제 해결 수단으로 사용할 수 없다고 볼 수 있다.
이와 같이 인자의 수가 정해지지 않는 경우에 해당하는 가변 인자가 들어올 경우 파이썬은 함수 정의부에서 별표를 매개변수의 앞에 넣어 사용 가능하다. 이때 가변적 인자는 튜플이나 리스트와 비슷하게 for - in 문에서 사용가능하다. 예제를 보도록 하자.

실행 결과

위와 같이 여러 인자를 받는 함수를 구현할 경우 이 인자들은 함수에 전달되기 전에 튜플 형태로 포장되어 전달된다. 따라서 함수 내부에서 이 인자들을 풀어서 살펴보기 위해서 for 루프를 사용하면 된다.
위 함수 greet은 *names와 같은 매개변수를 가지는데, greet() 함수를 호출할 때 인자가 2개가 되든 3개가 되든 for - in 문에서 인자의 값을 하나하나 접근하여 출력하는 것을 볼 수 있다. 또한 len()함수를 이용하여 가변 인자의 개수를 출력할 수도 있다.
인자 자체는 튜플로 나타난다.

실행 결과

또 다른 예제로 숫자의 합을 구하는 프로그램을 생각해 볼 수 있다.
인자를 튜플형식으로 받아서 하나하나 더하여 반환하는 식으로 인자들의 합을 구한다.

실행 결과

재귀함수란 함수 내부에서 자기 자신을 호출하는 함수이다. 유용한 문제 해결 기법으로, 절차적 기법으로 해결하기 어려운 문제를 직관적이고 간단하게 해결할 수 있다.
재귀함수의 예로 팩토리얼을 들어볼 수 있다.

실행 결과

재귀함수에서 중요한 점은 이 프로그램이 언제 종료되는가인데, 정의에 의해 1! = 1인 경우는 그 값이 정의되지만 1 이하의 값에 대해서는 팩토리얼을 정의할 필요가 없으므로 if문에서 n이 1 이하가 되면 1을 반환하면 된다. 이 조건문이 없으면 프로그램은 무한루프에 빠진다.
또 다른 예로는 피보나치 수열이 있다. 우선 피보나치 수열이 무엇인지 알아보자. 피보나치 수열은 첫번째와 두번째 항이 0과 1일 때 다음과 같은 식으로 정의된다.
Fn = Fn-1 Fn-2
이 정의에 따라 피보나치 수열은 0, 1, 1, 2, 3, 5, 8, 13, 21..... 과 같이 나아가게 되는데, 이 피보나치 수열은 재귀적 특징이 있으므로 다음과 같이 간단히 구현할 수 있다.

실행 결과

피보나치 수열 프로그램의 종료는 n이 1 이하일 때 n을 반환하는 것인데, n이 0이면 0을 1이면 1을 반환한다. 만일 fibonacci(2)가 호출되면 정의에 의하여 fiboncaci(1) + fibonacci(0)이 호출되어 결과는 1이 된다. 따라서 결과는 위와 같이 10개의 피보나치 수열을 정상적으로 출력하는 것을 볼 수 있을 것인다.
이와 같이 재귀함수는 코드를 직관적이고 간결하게 할 수 있어서 매우 유용한 풀이 기법이다.
그러나 위 함수에서 fibonacci(5)를 호출하면 이 코드는 재귀적 함수 호출이 매우 많이 일어날 것이다. 함수가 호출될 때 마다 함수는 이전에 수행한 과정을 메모리에 저장해야 하기 때문에 이와 같은 호출은 비효율적으로 수행된다. 따라서 재귀적 호출이 꼭 필요한가를 충분히 검토하고 프로그램을 작성하는 것이 좋을 것이다.
여태까지 사용한 프로그램은 print()함수를 사용하여 대화창에 출력을 내보내는 프로그램들이었다. 만약 입력을 주고 사용자의 입력을 처리하는 프로그래밍을 하려면 어떻게 해야 할까?
파이썬은 대화창에서 사용자로부터 입력을 받기 위한 입력함수인 input() 함수를 제공한다. input() 함수를 사용하면 사용자가 문자열을 입력할 수 있으며, 이 문자열을 변수에 저장하여 프로그램에서 사용할 수 있다.
다음 코드에서 input 함수를 사용한 다음 수행 결과 화면의 Hong Gildong 부분은 사용자가 키보드로 입력한 부분이다.
input 함수를 사용하면 대화창에서는 'Enter your name :' 이라는 문자열이 나타나며 사용자가 입력할 수 있도록 대기한다. 사용자가 입력을 마친 후 엔터키를 누르면 input 함수는 사용자가 입력한 문자열을 받아서 name 이라는 변수에 반환한다.
이후 print()문이 실행되어 사용자가 입력한 이름이 Hello 와 ! 사이에 나타나는 것을 확인할 수 있다.

실행 결과

이와 같이 대부분의 프로그래밍은 크게 3가지 절차로 이루어져있다. 먼저 사용자가 특정 명령을 키보드나 마우스 등 입력장치로 입력을 한다.
그러면 컴퓨터가 이 값을 받아 자료를 처리하고 마지막으로 결과를 모니터나 스피커, 프린터 같은 출력장치를 통해 출력하는 것이 통상적인 프로그램의 절차라고도 볼 수 있다.
파이썬에서는 사용자 입력 중 키보드 입력을 input() 함수를 통해 처리한다. 이 때 input()함수의 괄호 안에는 인자로 문자열을 넣을 수 있다. 이 문자열은 대화창에서 나타나게 되는데, 이 때문에 위 코드는 다음과 같이 더 간단하게 만들 수 있다.

실행 결과

2장에서 본 내용을 복습해보자. 문자열 '100'은 100이라는 값을 가지는 숫자와 다르다. 파이썬에서 100 + 1 은 숫자 사이의 덧셈이지만 '100'이라는 문자열과 '1'이라는 문자열의 덧셈 연산은 '100' + '1' = '1001' 이라는 문자의 결합이 된다.
반면 '100' + 1은 문자와 숫자의 덧셈이므로 연산이 불가능하다. 이유는 문자와 숫자의 연산이 파이썬에서 정의되어있지 않기 때문이다.

실행 결과

이런 문제를 해결하기 위해 문자열을 숫자로 바꾸는 방법, 숫자를 문자로 바꾸는 방법이 있다. 먼저 문자열을 숫자로 바꾸는 방법은 int() 함수나 float() 함수를 사용하는 것인데, int는 정수로, float는 실수로 바꾸는 함수이다.
숫자를 문자로 바꾸는 방법은 str() 함수를 사용하는 것이다.

이제 input()과 int()를 이용하여 두 수를 입력받아 두 수의 합을 구하는 프로그램을 만들어 보자.

실행 결과

이렇게 하나씩 입력할 수도 잇지만 한꺼번에 여러 개를 입력 할 수도 있다. 이를 위해서는 split() 메소드를 사용하여 입력된 문자를 공백 단위로 나누어 주는 작업이 필요하다.

input에는 문자열만 입력 가능하므로 정수를 표현하려면 int() 함수를 써 주는게 필요하다.
또, split() 메소드의 디폴트 구분자인 공백 대신 쉼표를 사용할 수도 있다. split(',')와 같이 입력할 수 있다.

파이썬에서 문자열은 단순히 화면에 출력을 내보내는 영역에 그치는 것이 아니다. 문자열은 자체적으로 다양한 기능을 수행하는 함수를 포함하고 잇는데 이와 같이 어떤 객체가 가지는 함수를 메소드라고 한다.
다음과 같은 내용을 파이썬 대화창에서 입력해 보자.

입력한 바와 같이 임의의 문자열에 마침표 연산을 하고 메소드를 호출하면 관련 기능이 수행된다. 여기서 사용한 upper() 메소드는 영문 소문자를 대문자로 변환한다. split() 메소드는 문자열 객체를 구문 문자열을 이용하여 문자열의 리스트로 만들어 준다.
이와 같이 한 문자열을 하나 이상의 개별 문자열로 나누는 문자를 구분자라 한다. 아무런 인자가 없을 경우 공백 문자가 구문자 역할을 한다.
함수와 메소드는 특정한 일을 하도록 정의된 동작을 수행한 다는 점에서 동일하다.
그런데, 함수는 호출하여 매개변수를 전달하여 특정한 동작을 수행하고 필요한 경우 그 결과를 반환하는 모든 프로그래밍 모듈을 함수라고 부를 수 있는 반면, 메소드는 객체지향 프로그래밍에서 다루는 객체에 부속되는 함수이다.
이 메소드는 자신을 가지는 객체의 속성 혹은 멤버 변수들에 대해 접근할 수 있다.
메소드는 인스턴스라고 하는 각각 다른 값을 가진 객체들마다 호출할 수 있으며, 이렇게 호출된 메소드는 동일한 이름의 메소드라고 하더라도 자신이 부속된 인스턴스의 현재 데이터들에 접근하여 일을 한다.
출력 부분이 하나면 쉼표를 사용하면 되는데, 여러개면 문자열 다음에 마침표 연산자를 사용하여 format() 메소드를 호출할 수 있다. format() 메소드의 인자로 출력하고자 하는 값이나 변수를 넣어서 출력할 수 있는데, 이와 같은 방법은 출력이 많을 경우 편리하다.
이 메소드는 원하는 문자열이나 숫자를 지정 위치에 지정 형식으로 출력하는데 매우 편리하게 사용할 수 있다. 이 때 사용되는 문자열을 템플릿이라고 하며 템플릿 내부에 빈 중괄호, 인덱스를 가진 중괄호, 포맷 문자열 등을 사용할 수 있다.
이 때 출력 메소드 format을 호출하는 문자열을 베이스 문자열이라 한다.

위와 같이 인자의 출력을 목적으로 사용되는 중괄호를 플레이스홀더라고 한다.

이 코드에서 'I like {} and {}' 는 'I like {0} and {1}'과 같은 의미이며 각각 'Python'을 {0} 플레이스홀더에, 'Java'를 {1} 플레이스 홀더에 전달한다. 이와 같이 플레이스홀더 내에 필요한 정수 값을 할당하여 출력 순서를 제어할 수 있다.
이제 앞에서 사용한 input() 함수와 플레이스 홀더, format() 메소드를 같이 활용해보자.

실행 결과

만약 print() 함수에서 위 코드와 같이 format() 메소드를 사용하지 않았다면 출력문은 비교적 복잡한 형태로 나타날 것이다. 이 경우 쉼표와 따옴표가 너무 많아서 코드를 읽기도 힘들고 오류가 날 가능성도 매우 높다.
ex) print('당신의 이름은'.name,'나이는',age,'직업은',job,'입니다.')
이제 format() 메소드의 고급 기능을 알아보자. format() 메소드는 플레이스홀더 내에 콜론을 찍고 앞서 배운 % 서식에서 사용한 것과 같이 출력의 크기와 형식을 지정해 줄 수 있다.
정수의 제곱, 세제곱값을 출력해보자.

실행 결과

출력은 잘 되었지만 숫자의 정렬이 제대로 이루어지지 않아 보기 불편한 감이 있다.
이제 {0}, {1}, {2} 플레이스홀더에 {0:3d}, {1:4d}와 같이 플레이스홀드 인덱스, 콜론, 3, 4와 같은 출력 칸의 크기, 출력형식 플래그 d를 지정해보자.

실행 결과

위의 print() 함수에서 사용된 3, 4, 5의 출력 칸의 전체 크기를 필드 폭이라고 한다. 실수 출력을 위해 10.2f, 10.3f, 10.4f과 같은 소수점 아래 자리수 출력 포매팅을 플레이스홀더에서 사용해보자.

위와 같이 3.1415926을 10.2f는 소수점 둘째자리, 10.3f는 소수점 셋째자리, 10.4f는 넷째자리이다.
10.3f를 예를들면, 소수점 넷째자리에서 반올림하여 3.141이 아닌 3.142가 출력된다.
또한 {0:.3f}와 같이 전체 칸의 크기를 지정하지 않고 소수점 아래 자리수만 지정하는 것도 가능하다.
이 경우 전체 칸의 크기를 지정하지 않았으므로 왼쪽 정렬이 발생된다.

프로그래밍에서 함수는 흔히 블랙박스라는 비유를 하는데, 그 이유는 입력값이 주어지면 함수가 동작을 하고 출력 값을 반환하는데, 우리는 이 함수가 어떻게 작동하는지 알 필요가 없다. 즉, 함수는 호출하는 사용자는 제대로 된 입력 값을 주고 그 결과인 출력(결과 값)을 사용만 하면 되기 때문이다.
파이썬에서 기본으로 구현되어 있어 제공하는 함수를 파이썬의 내장함수라고 한다. 파이썬에는 약 70개의 내장함수가 있다.
중요한 몇 개만 알아보자.

abs() 함수는 - 숫자를 입력하든지, + 숫자를 입력하든지 절댓값으로 나타내는 함수이다.
min() 함수는 200, 100, 300, 400 의 값을 가지는 정수들 중 가장 작은 값을 반환한다.
max() 함수는 min()함수와 반대로 가장 큰 값을 반환한다.
len() 함수는 문자열의 길이를 반환한다.
eval() 함수는 문자열을 받아와 해당 문자열의 내용을 수식화하여 평가한 다음 평가한 값을 반환해준다.
sorted() 함수는 문자열을 받아와서 알파벳 순으로 정렬해 반환한다.
reverse 인자를 사용하면 알파벳 역순으로 반환한다.
몇가지 더 알아보자. 파이썬은 객체지향 프로그래밍 언어이다. 이 언어의 핵심은 다양한 속성과 기능을 가진 객체들이 프로그램을 구성하는 방식이다.
이 때문에 파이썬의 객체는 다른 객체와 구별되는 고유한 식별값을 가지고 있고, id() 함수는 이 객체의 식별값을 정수형으로 반환한다. 이 식별값은 객체가 유지되는 한 다른 중복되지 않는 상수 값으로 남아있다.

다음은 type() 함수이다. 이 함수는 객체의 자료형을 반환한다. 객체 자료형은 class 'int'와 같이 표시된다.

마지막으로 chr(), ord()함수이다. chr() 함수는 유니코드 문자를 반환, ord() 함수는 그 반대의 역할을 한다.

내장함수는 프로그래밍을 효율적으로 할 수 있도록 도와준다. 뿐만 아니라 파이썬은 다양한 모듈을 제공하여 import 문을 이용해서 많은 모듈을 가져와 상황에 맞는 편한 코딩을 할 수 있다.