중첩함수

13718 단어 pythonpython

Nested Function

중첩 함수는 함수로 감싸진 함수를 뜻한다. Nested function 은 개념적인 용어로, 함수 안에 함수는 Inner function이라고 표현하고, 이 함수를 감싸고 있는 외부 함수를 Outer function 이라고 한다.

이때, 각 내부 함수들은 scope chain에 의해서 자신을 감싸고 있는 외부 함수의 메모리에 접근이 가능하다. (외부 함수가 가지고 있는 변수나 매개변수 등에 접근할 수 있고 사용할 수 있다는 뜻이다. 정확히는 외부 함수의 메모리를 복사해서 가지고 있다는 의미이다)

First-Class Function

first-class의 기본은 first-class citizen 이라는 개념이다

프로그래밍 언어에서 first-class citizen 속성을 가진다는 것은 어떤 객체를 다른 객체의 매개변수로 전달하거나, 함수의 반환값으로 사용하거나, 변수에 값으로 할당할 수 있다는 것을 의미한다. 요약하면 객체, 즉 자료형이나 함수등을 그 자체로 매개변수에 전달하거나 반환값으로 사용할 수 있으면 그것은 first-class citizen 속성을 가지고 있다고 할 수 있다.

###############################
# Case 1 : 함수(객체)를 값으로 할당하는 경우
def square(x):
    return x*x

square(10)
f = square
print(f(10))
# 100

###############################
# Case 2 : 함수(객체)를 함수(객체)의 매개변수로 넘기는 경우
def square(x):
    return x*x

def bind(func, arg_list):
    result = []
    for arg in arg_list:
        result.append(func(arg))
    
    return result

print(bind(square, [2,3,5]))
# [4,9,25]

Closure

Closure는 중첩함수의 일종이다. 개념 상으로는 Nested function의 하위 개념이다.

Closure란 함수가 사용하는 환경을 저장하는 것이다.

# 내부함수를 반환하지만 이때 이 함수와 관련된 환경을 따로 저장하고 있다.
def multiple_of_ten():
    square_root = 10 # nonlocal 변수

    def square(x):
        return square_root ** x

    return square

f = multiple_of_ten()

print(f(2))
# 100

Closure 언제 사용하는가?

  1. global 변수를 사용하고 싶지 않을 때 → 그 역할을 nonlocal 변수가 대신하여 데이터를 숨길 수 있다
  2. 클래스를 사용하지 않기 위해서 → 클래스는 함수에 비해 크기가 크기 때문에 다루는 변수나 함수가 많지 않은 경우 클래스 사용을 자제한다
  3. decorator → 어떤 함수를 실행하기 전이나 실행하고 난 뒤에 특정 기능을 수행하기 위한 기능

Closure 사용시 주의사항

nonlocal 변수들은 외부 함수가 실행되는 시점에서 생성되고 복사되어 내부 함수의 __closure__속성에 저장된다. 그래서 nonlocal 변수로 시간과 관련된 값을 사용하게 되면 의도하지 않은 결과가 나올 수 있다.

import datetime
import time

def logger():
    now = datetime.datetime.now()

    def print_log(message):
        return f"{now}, {message}"

    return print_log

logger = logger()

print(logger("start"))

time.sleep(10)

print(logger("After 10 sec")


기대하는 결과
>> 2020-12-03 15:38:30, start
>> 2020-12-03 15:38:40, After 10 sec.

실제 결과
>> 2020-12-03 15:38:30, start
>> 2020-12-03 15:38:30, After 10 sec.

Decorator

데코레이터는 말 그대로 장식을 하기 위한 문법으로, 기존의 클래스나 함수를 수정하지 않고 기능을 덧붙이는 기능을 한다.

def deco(func):
    def wrapper():
        print("before")
        ret = func()
        print("after")
        return ret
    return wrapper

@deco # deco(base) 와 같은 의미이다.
def base():
    print("base func")


base()

# f = deco(base)
# f()
# f() 와 base() 는 같은 결과를 가진다

Decorator 를 활용한 시간차 계산

import time

def measure_run_time(func):
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args)
        end = time.time()

        print(f"function running time : {end - start}")
        return result
    return wrapper

@measure_run_time
def worker(delay_time):
    time.sleep(delay_time)
    return 

worker(5)

# 결과값
# function running time : 5.004865884780884

좋은 웹페이지 즐겨찾기