Python Nesed Function/Decorator

노광오·2020년 6월 8일

Python

목록 보기
9/13

Nested Function(중첩 함수)

함수 안에 정의된 함수

중첩함수(nested function) 혹은 내부 함수는 는 상위 부모 함수 안에서만 호출 가능합니다. 부모 함수를 벗어나서 호출될 수 없습니다. 위의 코드에서 child_function 함수는 parent_function 안에서만 호출이 가능합니다.

Why use nested function?

1. 가독성

함수를 사용하는 이유중 하나는 반복되는 코드블럭을 함수로 정의해서 효과적으로 코드를 관리하고 가독성을 높이기 위함입니다.

중첩함수를 사용하는 이유도 동일합니다. 함수 안의 코드 중 반복되는 코드가 있다면 중첩함수로 선언하면 부모함수의 코드를 효과적으로 관리하고 가독성을 높일 수 있습니다.

2. Closure

중첩 함수를 사용하는 다른 큰 이유는 closure 입니다. Closure는 사전적의미는 패쇄 입니다.
도대체 뭘 패쇄 하는걸까요? 패쇄란 뭔가를 닫아서 가둔다는 의미가 있습니다.
파이썬에서 사용하는 closure도 어떤 것을 외부로부터 격리해 사용한다는 느낌이 더 큽니다.
그럼 무엇을 격리해 사용하는 것일까요?

바로 중첩 함수가 부모 함수의 변수나 정보를 가두어 사용하는 것을 closure라고 합니다.
그리고 부모함수는 중첩 함수를 리턴해줍니다. 그리하면 부모함수의 변수를 외부로부터 직접적인 접근은 격리하면서도 중첩 함수를 통해서 격리된 부모함수의 변수를 사용한 연산은 가능하게 해주는 것입니다.

정리하자면:

  1. 중첩 함수가 부모 함수의 변수나 정보를 중첩 함수 내에서 사용한다.
  2. 부모 함수는 리턴값으로 중첩 함수를 리턴한다.
  3. 부모 함수에서 리턴 했으므로 부모 함수의 변수는 직접적인 접근이 불가능 하지만 부모 함수가 리턴한 중첩 함수를 통해서 사용될 수 있다.

그렇다면 closure는 언제 사용하는 것일까요?
어떠한 정보를 기반으로 연산을 실행하고 싶지만 기반이 되는 정보는 접근을 제한하여 노출이 되거나 수정이 되지 못하게 하고 싶을때 사용합니다.

주로 factory 패턴을 구현할때 사용되는데요, factory는 공장이란 뜻이죠.
즉 뭔가를 생성해내는 패턴입니다. 주로 함수나 오브젝트를 생성해내는데 사용됩니다.
Factory에서 뭔가를 생성해 내기 위해서는 설정값이 필요할것입니다.
그 설정값을 노출하지 않아서 수정이 불가능하게 하면서 해당 설정값을 기반으로한 연산을 할 수 있는 함수를 만들때 closure를 사용할 수 있습니다.

예를 들어 보겠습니다.
만일 주어진 어떠한 숫자의 수(數) 을 구하는 함수는 다음과 같을 것입니다.

자 이제, 주어진 숫자의 승을 구하는게 아니라 특정 숫자의 승을 구하는 함수를 구현한다고 생각해봅시다. 예를 들어, 2의 승을 구하는 함수를 구현한다면 다음과 같습니다.

하지만 위의 함수는 2의 승밖에 구할 수 없습니다.
만일 특정 숫자의 숭을 구하는 함수가 필요 하지만 2가 아니라 설정되는 수의 승을 구하는 함수는 어떻게 구현할 수 있을까요?

이때 closure를 사용할 수 있습니다.

Decorator

  • 어떤 함수를 받아 명령을 추가한 뒤 이를 다시 함수의 형태로 반환하는 함수.
  • 어떤 함수의 내부를 수정하지 않고 기능에 변화를 주고 싶을 때 사용한다.
  • 말그대로 다른 함수를 꾸며주는 함수.

데코레이터 구조

클로저와 매우 흡사하게 생겼다는 것을 알 수 있다. 차이점이라면 데코레이터는 다른 함수를 인자로 받는다는 점이다.

간단한 데코레이터를 만들어보자. 아래 함수는 이름을 인자로 받아 자기소개를 출력해주는 함수이다.

그런데 인사도 없이 대뜸 자기 이름을 말해버리니까 버릇이 없어보여서 자기이름을 말하기 전에 인사를 먼저 하도록 바꿔주고 싶어졌다.
그래서 아래의 함수를 만들었다.

이 함수는 어떤 함수가 실행될 때 Hello라는 문자열을 출력해주도록 꾸며주는 데코레이터이다.

데코레이터의 적용

만든 데코레이터를 적용시켜서 introduce 함수를 꾸며보자.

decorator 함수에 호출하지 않은 introduce 함수 자체를 인자로 전달한다.

decorator 함수에 introduce 함수를 인자로 전달한 것을 decorated_introduce 라는 변수에 할당하였다.
이제 업그레이드 된 introduce 함수인 decorated_introduce 함수에 이름을 전달하여 잘 작동하는지 살펴보자.

<결과>
Hello
My name is Chaewon!

오오 이제 예의범절을 갖춘 개념찬 사람이 되었다!

어떤 과정을 통해 decorator 함수가 introduce 에 인사하는 기능을 추가해주는 것인지 살펴보자.

위의 과정에서는 데코레이터를 적용하기 위해
decorated_introduce 라는 새로운 변수를 만들어 decorator 함수에 introduce 함수를 전달한 값을 저장하였다.

이것은 아래와 같이 세련되게 바꿔줄 수 있다.

이것은 아래의 명령을 실행하는 것과 동일하다.

이렇게하면 원래의 함수를 호출할 때 데코레이터 함수가 적용된 결과를 출력한다.

<결과>
Hello
My name is Chaewon!

0개의 댓글