이 글의 작성자는 C/C++ 프로그래밍을 하던 사람이다. 이 글은 Python을 복습하며 작성하는 글이니, 부족한 부분이 있으면 얼마든지 피드백을 주시기 바란다.

 

그 동안 미처 하지 못했던 함수에 대한 이야기를 마무리해보자. 그렇다고 함수에 대한 모든 내용을 다루는 것은 아니니, 함수를 마스터했다고 생각하는 것은 곤란하다. 배움의 길은 끝이 없는 법이다.

 

내부 함수

함수 안에 또 다른 함수를 넣을 수도 있다. 함수 안에 함수가 있다고 해서 내부 함수(inner function)이라고 부르기도 하고, 중첩 함수(nested function)이라고 부르기도 한다.

def hello() :
    def hi() :
        print('hi')
    hi()
	...

내부 함수는 자신은 정의한 함수에서만 호출할 수 있다. 만약에 함수 밖에서 내부 함수를 호출하려고 하면 어떻게 될까?

def hello() :
    def hi() :
        print('hi')
    hi()

hi()

이 코드를 실행하면 다음 에러를 확인할 수 있을 것이다.

NameError: name 'hi' is not defined

내부 함수는 선언한 함수만 알고 있는 함수이기 때문에, 함수 밖에서는 이런 함수가 있는지도 모른다.

함수 안에서 중복코드가 있어서 이를 하나의 함수로 묶으려고 할 때, 다른 곳에서는 사용할 일이 없거나, 사용해서는 안되는 코드라면 위와 같이 함수 안에 선언을 하면 된다.

다음에 네임스페이스(namespace)에 대한 이야기를 할 때 다시 보게 될 것이다.

 

함수도 객체

Python은 모든 데이터를 객체로 표현한다 라는 이야기를 했었다. 함수도 객체다. 객체에 함수를 대입할 수도 있다. 아래 코드와 같이 함수 이름에 괄호를 쓰지 않으면 함수 객체를 변수에 대입하게 된다.

def hello() :
    print('hello')

a = hello

함수 뒤에 ()가 없어서 조금 어색해보이긴 하지만, 위의 코드는 정상적으로 작동하는 코드이다. 그러면 type()을 이용하면 어떤 타입이 나올까?

print(type(a))
<class 'function'>

‘function’, 즉 함수형 데이터 타입이라는 결과를 얻을 수 있다.

그러면 변수에 대입한 함수는 어떻게 호출해야 할까? 간단하다. 실제로 함수를 호출하듯이 변수 이름 뒤에 괄호를 붙이고 인자를 넣어주면 된다.

a()
hello

a를 호출했더니 hello()처럼 동작하는 것을 확인할 수 있다.

 

심지어는 인자로도 전달이 가능하다. 변수에 hello 함수를 대입하여 전달할 수도 있고, 직접 인자에 hello 함수를 전달해도 된다.

def callFunction(func):
    func()

def hello():
    print('hello')

a = hello
callFunction(a)
callFunction(hello)

위의 코드를 실행하면 ‘hello’가 2번 출력되는 것을 확인할 수 있을 것이다.

매개변수 func가 함수인지 아닌지 어떻게 알고 저렇게 함수를 호출하는거냐? 라는 의문이 들 수 있는데, 일단 호출해보고 아니면 에러를 발생시킬 뿐이다.

 

람다 함수(lambda function)

callFunction 함수에게 함수 객체를 전달하기 위해, 우리는 hello 함수를 새롭게 정의했었다. 그런데 단순히 callFunction 함수에게 인자로 전달하기 위한 용도로만 만들었다면? 그것 때문에 함수를 선언하고 이름까지 정하는 수고를 해야 한다면?

‘별게 다 귀찮네’ 라는 생각을 할 수도 있을 수도 있다. 하지만 위의 과정이 빠진다면 좀 더 편리해질 수도 있는 것은 사실이다. (물론 독이 될 수도 있다) 그래서 Python은 이름없는 일회용 함수를 만드는 방법을 제공한다. 그것이 람다 함수(lambda function)이다.

lambda parameters: expression

람다 함수는 lambda로 시작한다.
parameters에는 매개변수들을 집어넣으면 된다. 필요한 수 만큼 매개변수를 함수에서 하듯이 집어넣으면 되고, 없으면 안넣어도 된다.
expression에는 람다 함수에서 수행할 코드를 집어넣으면 된다.

그러면 위의 callFunction을 사용하는 코드를 람다 함수로 바꿔보자.

def callFunction(func):
    func()

callFunction(lambda: print('hello'))

똑같은 동작을 하는 코드는 지우고 생각하면, 7줄짜리 코드가 4줄짜리 코드로 변신하였다. 코드의 양이 줄어든 것이 체감이 될 것이다.

물론 람다 함수도 변수에 대입할 수 있다.

hello = lambda: print('hello')

 

아직 다루지 않은 함수의 기능들이 좀 남아있다. (클로져라던가 데코레이터라던가) 이것들에 대해서는 나중에 따로 다루기로 한다.

 

Categories:

Updated:

Comments