함수

[funcchap]

함수 호출

[functionchap]

프로그래밍에서 함수는 계산을 수행하는 연속된 문장들의 집합에 이름을 부여한 것입니다. 함수를 정의할 때 이름과 연속된 문장들을 지정합니다. 나중에, 이름을 사용하여 함수를 “호출”할 수 있습니다. 우리는 이미 함수 호출의 한가지 사례를 봤습니다:

>>> type(32)
<type 'int'>

함수의 이름은 type입니다. 괄호 안의 표현식은 함수의 인자라고 불립니다. 이 함수의 경우에, 결과는 인자의 형입니다.

보통 함수가 인자를 “받”고 결과를 “돌려준다”고 합니다. 결과는 반환값이라고 불립니다.

형변환 함수

파이썬은 값을 한 형에서 다른 형으로 바꾸는 내장 함수들을 제공합니다. int함수는 아무 값이나 받아서, 할 수 있다면, 정수로 바꿔주거나, 그럴 수 없다고 불평합니다.

>>> int('32')
32
>>> int('Hello')
ValueError: invalid literal for int(): Hello

int는 실수 값을 정수로 바꿀 수 있습니다만, 반올림하지 않고 소수점 이하를 잘라냅니다:

>>> int(3.99999)
3
>>> int(-2.3)
-2

float는 정수와 문자열을 실수로 바꿉니다:

>>> float(32)
32.0
>>> float('3.14159')
3.14159

마지막으로, str은 인자를 문자열로 바꿉니다:

>>> str(32)
'32'
>>> str(3.14159)
'3.14159'

수학 함수

파이썬에는 잘 알려진 수학 함수들의 대부분을 제공하는 수학 모듈이 있습니다. 모듈은 서로 관련 있는 함수들을 모아놓은 파일입니다.

모듈은 사용하기 전에 들여와야만 합니다:

>>> import math

이 문장은 math 라는 이름의 모듈 객체를 만듭니다. 인쇄하면 모듈 객체에 대한 약간의 정보를 얻을 수 있습니다:

>>> print math
<module 'math' (built-in)>

모듈 객체는 모듈에 정의된 함수와 변수들을 갖고 있습니다. 함수에 접근하기 위해서는 모듈의 이름과 함수의 이름을 점으로 연결해야 합니다. 이 형식을 점 표기법이라고 부릅니다.

>>> ratio = signal_power / noise_power
>>> decibels = 10 * math.log10(ratio)

>>> radians = 0.7
>>> height = math.sin(radians)

첫 번째 예는 (signal_powernoise_power가 정의되어 있다고 가정할 때) 신호 대 잡음 비를 데시벨로 계산하기 위해 log10을 사용합니다. math 모듈은 log 도 제공하는데, e 를 밑으로 하는 자연로그를 계산합니다.

두 번째 예는 radians의 사인을 구합니다. 변수 명은 sin 과 다른 삼각함수들(cos, tan, 등.)이 라디안 단위의 인자를 받아들인다는 힌트입니다. 디그리를 라디안으로 바꾸기 위해서는 360으로 나눈 후에 \(2 \pi\) 를 곱하면 됩니다:

>>> degrees = 45
>>> radians = degrees / 360.0 * 2 * math.pi
>>> math.sin(radians)
0.707106781187

math.pi 표현식은 math 모듈의 변수 pi를 제공합니다. 변수의 값은 \(\pi\) 의 근사값인데, 15자리까지 정확합니다.

삼각법을 안다면, 2의 제곱근을 2로 나눠서 앞의 결과와 비교해볼 수 있습니다.

>>> math.sqrt(2) / 2.0
0.707106781187

합성

지금까지, 우리는 프로그램의 요소들—변수, 표현식, 문장—을 어떻게 결합하는지에 대해서는 말하지 않고 따로 때어서 살펴봤습니다.

프로그래밍 언어의 가장 유용한 기능들 중 하나는 작은 부품들을 모아서 합성하는 능력입니다. 예를 들어, 함수의 인자로 대수 연산자를 포함하는 모든 종류의 표현식을 사용할 수 있습니다:

x = math.sin(degrees / 360.0 * 2 * math.pi)

그리고 함수 호출마저 가능합니다:

x = math.exp(math.log(x+1))

값을 넣을 수 있는 모든 곳에, 임의의 표현식을 넣을 수 있습니다. 단, 대입문의 좌변에는 변수 명이 와야 합니다. 그 외의 표현식이 좌변에 나오면 문법 오류입니다(이 규칙의 예외는 나중에 보게 됩니다).

>>> minutes = hours * 60                 # 좋아요
>>> hours * 60 = minutes                 # 안돼요!
SyntaxError: can't assign to operator

새 함수 만들기

지금까지, 우리는 파이썬에 따라오는 함수들을 쓰기만 했습니다만, 새 함수를 만들 수도 있습니다. 함수 정의는 새 함수의 이름과 함수가 호출됐을 때 실행할 연속적인 문장들을 지정합니다.

여기 예가 있습니다:

def print_lyrics():
    print "I'm a lumberjack, and I'm okay."
    print "I sleep all night and I work all day."

def 는 함수 정의임을 나타내는 예약어입니다. 이 함수의 이름은 print_lyrics 입니다. 함수명의 규칙은 변수명과 동일합니다: 영문자, 숫자와 밑줄 문자가 가능합니다만, 처음에 숫자가 올 수는 없습니다. 예약어를 함수 명으로 사용할 수는 없고, 변수와 함수에 같은 이름을 사용하지 않도록 해야 합니다.

이름 뒤에 오는 빈 괄호는 이 함수가 아무런 인자도 받아들이지 않음을 뜻합니다.

함수 정의의 첫 줄은 헤더, 나머지 부분은 바디라고 불립니다. 헤더는 콜론으로 끝나야 하고, 바디는 들여쓰기 해야 합니다. 관습적으로, 들여쓰기는 항상 4개의 공백문자를 사용합니다. 바디에 나올 수 있는 문장의 수에는 제한이 없습니다.

인쇄문의 문자열은 큰따옴표를 사용하고 있습니다. 작은따옴표와 큰따옴표는 같은 일을 합니다; 대부분의 사람들은 작은 따옴표를 사용하는데, 지금처럼 문자열 안에 작은 따옴표(아포스트로피 문자이기도 하지요)가 나올 때만 예외입니다.

대화형 모드에서 함수 정의를 입력하면, 인터프리터는 정의가 완료되지 않았음을 알리기 위해 생략 부호(...)를 인쇄합니다:

>>> def print_lyrics():
...     print "I'm a lumberjack, and I'm okay."
...     print "I sleep all night and I work all day."
...

함수를 끝내기 위해서는, 빈 줄을 입력해야 합니다(스크립트 모드에서는 필요 없습니다).

함수를 정의하면 같은 이름의 변수가 만들어집니다.

>>> print print_lyrics
<function print_lyrics at 0xb7e99e9c>
>>> type(print_lyrics)
<type 'function'>

print_lyrics 의 값은 함수 객체이고 'function' 형에 속합니다.

새로 만든 함수를 호출하는 문법은 내장 함수와 같습니다:

>>> print_lyrics()
I'm a lumberjack, and I'm okay.
I sleep all night and I work all day.

일단 함수를 정의하면, 다른 함수 안에서 사용할 수 있습니다. 예를 들어, 앞에 나온 후렴구를 반복하기 위해, repeat_lyrics 라는 함수를 만들 수 있습니다:

def repeat_lyrics():
    print_lyrics()
    print_lyrics()

그리고 나서는 repeat_lyrics를 호출합니다:

>>> repeat_lyrics()
I'm a lumberjack, and I'm okay.
I sleep all night and I work all day.
I'm a lumberjack, and I'm okay.
I sleep all night and I work all day.

하지만 노래가사가 실제로 이렇지는 않습니다.

정의와 사용

앞 절에서의 코드 조각들을 모으면, 전체 프로그램이 이렇게 됩니다:

def print_lyrics():
    print "I'm a lumberjack, and I'm okay."
    print "I sleep all night and I work all day."

def repeat_lyrics():
    print_lyrics()
    print_lyrics()

repeat_lyrics()

이 프로그램에는 두 개의 함수 정의가 있습니다: print_lyricsrepeat_lyrics. 함수 정의는 다른 문장들처럼 실행됩니다만, 그 결과로 함수 객체가 만들어 집니다. 함수 정의 안에 들어있는 문장들은 함수가 호출되기 전까지 실행되지 않고, 함수 정의는 출력을 만들지 않습니다.

여러분이 짐작하듯이, 함수를 실행하기 전에 만들어야만 합니다. 다른 말로 하면, 함수는 처음으로 호출되기 전에 함수 정의가 실행되어야 합니다.

[연습 3.1.]

이 프로그램의 마지막 줄을 처음으로 옮겨서 함수 정의 앞에 함수 호출이 나오도록 만드세요. 프로그램을 실행한 후에 어떤 오류 메시지가 나오는지 살펴보세요.

[연습 3.2.]

함수 호출을 다시 끝으로 돌려보내고, print_lyrics 함수 정의를 repeat_lyrics 정의 뒤로 옮기세요. 프로그램을 실행하면 어떤 결과를 얻게 될까요?

실행 흐름

함수가 처음 사용되기 전에 정의됨을 확실히 하기 위해서, 문장들이 실행되는 순서를 알아야만 하는데, 이를 실행 흐름이라고 합니다.

실행은 항상 프로그램의 첫 문장으로 시작합니다. 문장은 한 번에 하나씩 위에서 아래로 실행됩니다.

함수 정의가 프로그램의 실행 흐름을 바꾸지는 않습니다만, 함수 안의 문장들이 함수가 호출 되기 전까지는 실행되지 않는다는 것을 기억해두세요.

함수 호출은 실행 흐름에서 우회로 같은 것입니다. 다름 문장으로 넘어가는 대신에, 함수의 바디로 뛰어서 그곳에 있는 모든 문장들을 실행 한 후에 돌아와서 하던 일을 계속합니다.

함수가 다른 함수를 호출할 수 있다는 것을 기억해내기 전까지는 간단한 것처럼 들립니다. 함수가 실행되는 도중, 프로그램은 다른 함수에 있는 문장들을 실행해야 할 수가 있습니다. 그런데 다른 함수를 실행하는 동안, 또 다른 함수를 실행해야 할 수도 있습니다!

다행히도, 파이썬은 자신이 어디쯤 와 있는지 잘 기억합니다, 그래서 함수가 끝날 때마다 호출한 함수로 돌아가서 계속합니다. 프로그램의 끝에 도달하면 종료합니다.

이 지저분한 이야기가 주는 교훈은 뭘까요? 여러분이 프로그램을 읽을 때, 항상 위에서 아래로 읽어나가기를 원하지는 않을 거라는 사실입니다. 때로 실행 흐름을 따르는 것이 더 적절할 수 있습니다.

매개변수와 인자

[parameters]

우리가 본 몇몇 내장 함수들은 인자를 요구합니다. 예를 들어, math.sin 을 호출할 때, 인자로 숫자를 넘겨줍니다. 어떤 함수들은 하나 이상의 인자들을 받아들입니다: math.pow 는 밑과 지수 두 개를 받아들입니다.

함수 내부에서, 인자는 매개변수라고 불리는 변수에 대입됩니다. 여기에 인자를 받아들이는 사용자 정의 함수의 예가 있습니다:

def print_twice(bruce):
    print bruce
    print bruce

이 함수는 인자를 bruce하는 매개변수에 대입합니다. 함수가 호출될 때, 매개변수의 값을 (그 것이 무엇이건) 두 번 인쇄합니다.

이 함수는 인쇄될 수 있는 모든 값과 함께 사용될 수 있습니다.

>>> print_twice('Spam')
Spam
Spam
>>> print_twice(17)
17
17
>>> print_twice(math.pi)
3.14159265359
3.14159265359

내장 함수에 적용되는 합성과 동일한 규칙이 사용자 정의 함수에도 적용되기 때문에, 우리는 print_twice의 인자로 모든 종류의 표현식들을 사용할 수 있습니다:

>>> print_twice('Spam '*4)
Spam Spam Spam Spam
Spam Spam Spam Spam
>>> print_twice(math.cos(math.pi))
-1.0
-1.0

인자는 함수가 호출되기 전에 계산되기 때문에, 앞의 예에서 표현식 'Spam '*4 과 math.cos(math.pi)는 오직 한번만 계산됩니다.

변수를 인자로 사용할 수도 있습니다:

>>> michael = 'Eric, the half a bee.'
>>> print_twice(michael)
Eric, the half a bee.
Eric, the half a bee.

인자로 전달한 변수의 이름 (michael) 은 매개변수의 이름 (bruce) 과 아무런 관계도 없습니다. 값이 원래 집(호출자)에서 어떤 이름으로 불렸는지는 중요하지 않습니다, print_twice 에서 우리는 모든 이를 bruce라 부릅니다.

변수와 매개변수는 지역적이다

함수 안에서 변수를 만들면 지역적입니다. 그 변수는 오직 해당 함수 내에서만 존재한다는 뜻입니다. 예를 들어:

def cat_twice(part1, part2):
    cat = part1 + part2
    print_twice(cat)

이 함수는 두 개의 인자를 받아들여서, 이어 붙인 다음, 두 번 인쇄합니다. 여기 사용 예가 있습니다:

>>> line1 = 'Bing tiddle '
>>> line2 = 'tiddle bang.'
>>> cat_twice(line1, line2)
Bing tiddle tiddle bang.
Bing tiddle tiddle bang.

cat_twice 이 끝날 때 변수 cat은 제거됩니다. 만약 인쇄하려고 한다면 예외를 만나게 됩니다:

>>> print cat
NameError: name 'cat' is not defined

매개변수도 지역적입니다. 예를 들어, print_twice 외부에 bruce 같은 것은 없습니다.

스택 다이어그램

[stackdiagram]

어떤 변수가 어디에서 사용되었는지 따라가기 위해, 때로 스택 다이어그램을 그리는 것이 쓸모 있습니다. 상태도처럼 스택 다이어그램은 각 변수들의 값을 보여주는데, 각 변수가 속한 함수도 보여줍니다.

각 함수는 프레임으로 표현됩니다. 프레임은 옆에 함수의 이름이 있고 안에 함수의 변수들이 있는 상자입니다. 앞의 예를 위한 스택 다이어그램이 그림 [fig.stack]에 있습니다.

stack

[fig.stack]

프레임은 어떤 함수가 어떤 함수를 호출하는지를 표시하도록 쌓아 올려 배치됩니다. 이 예에서, print_twicecat_twice 에 의해 호출되고, cat_twice__main__ 에 의해 호출됩니다. __main__ 는 최 상단 프레임을 위해 특별히 마련된 이름입니다. 어떤 함수에도 속하지 않은 변수를 만들면, __main__에 속하게 됩니다.

각 매개변수는 대응하는 인자와 같은 값을 가리킵니다. 그래서, part1 은 line1과 같은 값을 갖고, part2는 line2와 같은 값을 가지며, bruce는 cat과 같은 값을 갖습니다.

함수 호출 중에 오류가 발생하면, 파이썬은 함수의 이름을 인쇄하고, 그 함수를 호출한 함수의 이름을 인쇄하고, ... 이런 식으로 __main__ 에 이르는 모든 함수들을 인쇄합니다.

예를 들어, print_twice 안에서 cat을 사용하려고 하면 NameError가 발생합니다:

Traceback (innermost last):
  File "test.py", line 13, in __main__
    cat_twice(line1, line2)
  File "test.py", line 5, in cat_twice
    print_twice(cat)
  File "test.py", line 9, in print_twice
    print cat
NameError: name 'cat' is not defined

이 함수의 목록을 트레이스백이라고 합니다. 오류가 발생했을 때 실행하고 있던 프로그램 파일, 줄, 함수를 알려줍니다. 오류를 일으킨 한 줄의 코드도 보여줍니다.

트레이스백에 나오는 함수들의 순서는 스택 다이어그램의 프레임 순서와 같습니다. 가장 마지막에 실행 중이던 함수가 가장 아래에 나옵니다.

결과가 있는 함수와 없는 함수

우리가 사용하고 있는 어떤 함수들은, 수학 함수들처럼, 결과를 제공합니다; 더 좋은 이름이 없는 관계로, 이들을 결과가 있는 함수라고 부르겠습니다. 다른 함수들은, print_twice 처럼, 일을 하지만 결과를 돌려주지는 않습니다. 이들을 결과가 없는 함수 라 부릅니다.

결과가 있는 함수를 호출할 때, 대부분의 경우 결과로 뭔가 하기를 원할 겁니다; 예를 들어, 변수에 대입하거나 표현식의 일부로 사용할 수 있습니다.

x = math.cos(radians)
golden = (math.sqrt(5) + 1) / 2

대화형 모드에서 함수를 호출하면, 파이썬은 결과를 표시합니다:

>>> math.sqrt(5)
2.2360679774997898

그러나 스크립트에서 결과가 있는 함수를 단지 호출하기만 한다면 결과값은 영원히 잃어버리게 됩니다!

math.sqrt(5)

이 스크립트는 5의 제곱근을 계산합니다만, 결과를 저장하거나 표시하지 않기 때문에 그다지 쓸모가 없습니다.

결과가 없는 함수는 뭔가를 화면에 표시하거나 다른 효과를 일으킬 수 있습니다만, 결과값은 없습니다. 만약 결과를 변수에 대입하려고 시도한다면, None이라 불리는 특별한 값을 얻게 됩니다.

>>> result = print_twice('Bing')
Bing
Bing
>>> print result
None

None 값은 문자열 'None'과 다릅니다. 자신만의 형을 갖는 특별한 값입니다:

>>> print type(None)
<type 'NoneType'>

아직까지 우리가 작성한 모든 함수들은 결과가 없는 것들입니다. 곧 결과가 있는 함수들을 쓰기 시작할 것입니다.

왜 함수를 사용하는가?

프로그램을 함수들로 나누는 수고를 들이는 이유가 분명치 않을 수 있습니다. 몇가지 이유가 있습니다:

  • 함수를 새로 만들게 되면 일련의 문장들에 이름을 붙일 기회를 갖게 되는데, 프로그램을 읽고 디버깅하기 쉽도록 만들어줍니다.
  • 함수들은 반복적인 코드들을 제거해서 프로그램을 작게 만들 수 있습니다. 나중에, 고치야 할 경우에 한 곳만 손보면 됩니다.
  • 긴 프로그램을 여러 함수로 나누는 것은, 한번에 하나씩 디버깅해서 작동하는 전체로 조립할 수 있도록 합니다.
  • 잘 설계된 함수들은 종종 많은 프로그램에 쓸모가 있습니다. 한번만 쓰고 디버깅을 하면, 다시 사용할 수 있습니다.

from으로 들여오기

파이썬은 모듈을 들여오는 두 가지 방법을 제공합니다; 우리는 이미 하나를 봤습니다:

>>> import math
>>> print math
<module 'math' (built-in)>
>>> print math.pi
3.14159265359

math를 들여오면, math 라는 이름의 모듈을 얻게 됩니다. 모듈 객체는 pi와 같은 상수들과, sin 이나 exp 같은 함수들을 갖고 있습니다.

그러나 pi를 직접 참조하려고 하면, 오류가 발생합니다.

>>> print pi
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'pi' is not defined

대신에, 이런 방법으로 모듈의 객체를 들여올 수 있습니다:

>>> from math import pi

이제 점 표기법 없이 pi 를 직접 참조할 수 있습니다.

>>> print pi
3.14159265359

또는 별 연산자를 사용해서 모듈로부터 모든 것을 들여올 수 있습니다:

>>> from math import *
>>> cos(pi)
-1.0

수학 모듈로부터 모든 것을 들여올 때의 장점은 코드가 더 간단해 진다는 것입니다. 단점은 다른 모듈들에서 정의된 이름들이나 여러분이 정의한 변수들의 이름들과 부딪힐 수 있다는 것입니다.

디버깅

[editor]

만약 여러분이 스크립트를 쓰는데 텍스트 편집기를 사용하고 있다면, 공백과 탭에 관한 문제를 만났을 수 있습니다. 이 문제를 피하는 가장 좋은 방법은 (탭 없이) 공백만을 사용하는 것입니다. 파이썬을 아는 대부분의 텍스트 편집기는 기본적으로 이렇게 합니다만, 어떤 것들은 그렇지 않습니다.

탭과 공백은 보통 보이지 않기 때문에 디버깅하기 어렵습니다. 여러분 대신 들여쓰기를 처리해주는 편집기를 찾으세요.

또한, 잊지 말고 실행 전에 여러분의 프로그램을 저장하세요. 어떤 개발 환경들은 이를 자동적으로 처리해줍니다만, 어떤 것들은 그렇지 않습니다. 이럴 때, 여러분이 텍스트 편집기에서 보고 있는 프로그램은 실행되고 있는 프로그램과 다른 것입니다.

똑 같은, 잘못된, 프로그램을 계속 반복해서 실행한다면 디버깅에는 기나긴 시간이 필요할 수 있습니다!

여러분이 보고 있는 프로그램이 실행하고 있는 코드임을 확실히 하세요. 확신할 수 없다면, print 'hello' 같은 것을 프로그램의 처음에 넣고 다시 실행해 보세요. hello 를 볼 수 없다면, 올바른 프로그램을 실행하고 있는 것이 아닙니다!

용어

함수 function:
쓸모 있는 일을 하는 일련의 문장들에 이름을 붙인 것. 함수는 인자를 취하거나 취하지 않을 수 있고, 결과를 주거나 주지 않을 수 있다.
함수 정의 function definition:
이름, 매개변수, 실행할 문장들로 새 함수를 만드는 문장.
함수 객체 function object:
함수 정의에 의해 만들어지는 값. 함수의 이름은 함수 객체를 가리키는 변수다.
헤더 header:
함수 정의의 첫 번째 줄.
바디 body:
함수 정의에 포함된 일련의 문장들.
매개변수 parameter:
인자로 전달된 값들을 가리키기 위해 함수 내부에서 사용되는 이름.
함수 호출 function call:
함수를 실행하는 문장. 함수의 이름과 그 뒤를 따르는 인자 목록으로 구성된다.
인자 argument:
함수가 호출될 때 함수로 제공되는 값. 이 값은 함수의 해당 매개변수로 대입된다.
지역 변수 local variable:
함수 내에서 정의된 변수. 지역 변수는 함 수 내에서만 사용될 수 있다.
반환값 return value:
함수의 결과. 함수 호출이 표현식으로 사용되면, 결과값이 표현식의 값이다.
결과가 있는 함수 fruitful function:
값을 돌려주는 함수.
결과가 없는 함수 void function:
값을 돌려주지 않는 함수.
모듈 module:
관련 있는 함수들과 다른 정의들을 모아놓은 파일.
들여오기 문 import statement:
모듈 파일을 읽어 들여 모듈 객체를 만드는 문장.
모듈 객체 module object:
import 문장에 의해 만들어지는 값. 모듈에 정의된 값들에 접근할 수 있도록 한다.
점 표현법 dot notation:
모듈 명 뒤에 점(마침표)과 함수이름을 붙여서 다른 모듈의 함수를 호출하는 문법.
합성 composition:
표현식을 모아 더 큰 표현식을 구성하거나, 문장을 모아 더 큰 문장을 구성하는 것.
실행 흐름 flow of execution:
프로그램이 실행될 때 문장이 실행되는 순서.
스택 다이어그램 stack diagram:
함수들, 함수의 변수들, 변수들이 가리키는 값들을 쌓아 올려 도식화한 것.
프레임 frame:
함수 호출을 표현하는 스택 다이어그램의 상자. 지역 변수와 함수의 매개 변수를 포함한다.
트래이스백 traceback:
예외가 발생했을 때 인쇄되는, 실행 중인 함수들의 목록.

연습

[연습 3.3.]

파이썬은 문자열의 길이를 돌려주는 내장 함수 len을 제공합니다. 그래서 len('allen')의 값은 5입니다.

s라는 문자열을 매개변수로 받아서, 마지막 글자가 화면의 70번째 열에 위치하도록, 앞에 충분한 공백을 추가해서 인쇄하는 함수 right_justify를 작성하세요.

>>> right_justify('allen')
                                                                 allen

[연습 3.4.]

함수 객체는 변수에 대입하거나 인자로 전달할 수 있는 값입니다. 예를 들어, do_twice는 함수 객체를 인자로 받아들여 두 번 호출해주는 함수입니다:

def do_twice(f):
    f()
    f()

여기 print_spam 이라는 이름의 함수를 두 번 호출하도록 do_twice를 사용한 예가 있습니다.

def print_spam():
    print 'spam'

do_twice(print_spam)
  1. 이 예를 스크립트에 입력해서 실험해 보세요.
  2. 두 개의 인자를, 함수 객체와 값, 받아들여 함수를 두 번 호출할 때 인자로 값을 전달하도록 do_twice를 수정하세요.
  3. print_spam 를 더 일반화시킨 함수 print_twice를 작성하세요. 문자열을 매개변수로 받아들여 두 번 인쇄합니다.
  4. 수정된 do_twice를 사용해서, print_twice 를 두 번 호출하면서 'spam'를 인자로 전달하세요.
  5. 함수 객체와 값을 받아들여 인자로 값을 전달하면서 함수를 네 번 호출하는 새 함수 do_four를 정의하세요. 함수의 바디에는 네 개가 아니라 단지 두 개의 문장만 있어야 합니다.

답: http://thinkpython.com/code/do_four.py.

[연습 3.5.]

이 연습은 지금까지 배운 문장들과 기능들 만으로 해결할 수 있습니다.

  1. 다음과 같은 격자를 그리는 함수를 작성하세요:

    + - - - - + - - - - +
    |         |         |
    |         |         |
    |         |         |
    |         |         |
    + - - - - + - - - - +
    |         |         |
    |         |         |
    |         |         |
    |         |         |
    + - - - - + - - - - +
    

    힌트: 한 줄에 하나 이상의 값을 인쇄하려면, 콤마로 분리해서 나열하면 됩니다:

    print '+', '-'
    

    나열이 콤마로 끝나면, 파이썬이 줄을 끝내지 않은 채로 둬서, 다음에 인쇄되는 값은 같은 줄에 나타난다.

    print '+',
    print '-'
    

    이 문장의 출력은 '+ -'다.

    print만으로 구성된 문장은 현재 줄을 끝내고, 다음 줄로 넘긴다.

  2. 4개의 행과 4개의 열을 갖는 비슷한 격자를 그리는 함수를 작성하세요.

답: http://thinkpython.com/code/grid.py. 출처: 이 연습은 Oualline의 연습에 기반합니다. Practical C Programming, Third Edition, O’Reilly Media, 1997.