Home > Today I Learned > 2026_06_TIL > 2026-06-25 일지

2026-06-25 일지
python

함수형 프로그래밍

순수 함수(Pure Function)

  1. 동일한 입력이 주어지면 동일한 결과를 반환
  2. 부수효과(Side Effect)가 없음

수학의 함수 $f(x) = x^2 + 1$과 유사하다. 입력과 출력 사이의 순수한 관계만 존재하는 함수

    def add(a,b):
        return a+b
    
    total =0
    
    def count_total():
        global total
        total += 1
        return total
    
    print(count_total())

람다대수(Lambda Calculus)

$\lambda x. x+1 $

double = lambda x: x * 2

print(double(5))

outer에 들어가는 매개변수가 계속 살아간다.
이렇게 사용하는 것을 클로져라고 한다.
값을 집어넣고 쓸 수 있기 때문에 변수가 기억을 한다.

def outer(x):
    def inner(y):
        return x + y
    return inner

add5 = outer(5)
add10 = outer(10)

print(add5(3)) #8
print(add10(3)) #13
print(add5(7)) #12

자유변수

함수 내부에서 사용되지만, 해당 함수 안에서 정의되지 않은 변수.
클로저에서 내부 함수가 참조하는 외부 함수의 변수 -> 자유변수

Python에서는 변수를 찾을 때 LEGB 규칙을 따른다.
‘Local(지역) -> Enclosing(감싸는 함수의 블럭) -> Global(모듈 전역) -> Built-in(내장)’

내부 함수에서 외부 함수의 변수를 읽는 것은 자동으로 자유변수 처리를 한다.
그러나 변수를 쓰거나 재할당하려면 반드시 ‘nonlocal’ 키워드를 사용해야 한다.

‘nonlocal’은 전역 스코프가 아니라 Enclosing 스코프 변수를 수정할 때 사용한다.

def outer():
    x = 1
    def outer2():
        def inner():
            nonlocal x
            x += 10
        inner()
        print(x)
    outer2()
outer()

데코레이터(Decorator)

데코레이터는 기존의 함수나 클래스를 수정하지 않고, 동작을 확정하거나 변경하는 디자인 패턴을 의미한다.
데코레이터는 본질적으로 다른 함수를 인자로 받는다. 해당 함수의 동작이 추가된 새로운 함수를 반환하는 고차함수.
즉, 클로저를 기반으로 구현

#실행시간 측정하는 기능
import time
def heavy_add(a,b):
    time.sleep(0.01)
    return a+b
    
def heavy_multiply(a,b):
    time.sleep(1)
    return a*b

start = time.time()
result = heavy_add(1,2)
elapsed = time.time() - start

print(f'heavy_add는 {elapsed:.4f}초가 소요되었고, 결과는 {result}입니다.')

파이썬에서는 언어차원에서 이러한 데코레이터 패턴을 지원해준다.
@데코레이터 문법

import time
import functools

def timer(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start = time.time()
        result = func(*args, **kwargs)
        elapsed = time.time() - start
        print(f'{func.__name__}:{elapsed:.2f}초 소요되었고, 결과는 = {result}입니다.')
        return result
    return wrapper

@timer
def heavy_multiply(a,b):
    time.sleep(1)
    return a*b

heavy_multiply(5,5)