Python 언어의 특징
Python은 동적 언어이기 때문에 클래스에서 정보의 은닉을 지원하지 않는다.
사용자가 만약 클래스나 객체 변수에 접근하여 프로그램에 잘못된 동작이 일어날 수 있다.
다른 언어는 private, public 등의 키워드를 제공하여 이런 가능성을 원천 차단해버리지만 Python은 가능성을 열어두고 잘못된 동작이 일어날 시 이를 사용자의 책임으로 전가한다.
Python처럼 클래스 정보의 은닉을 지원하지 않는 언어에서 정보의 은닉을 사용하고 싶을 때 사용할 수 있는 것이 클로져 함수(Closure Function)다.
클로져 함수(Closure Function)
클로져 함수의 필요성을 다음과 같이 정리할 수 있겠다.
1. 클래스 없이 객체를 만들고 싶을 때
2. 정보를 은닉하고 싶을 때
def append_string():
strings = [] # 사용자는 strings에 접근불가!(은닉)
def func(string):
strings.append(string)
return strings
return func
f = append_string()
print(f('a')) # ['a']
print(f('b')) # ['a', 'b']
print(f('c')) # ['a', 'b', 'c']
클로져 함수가 되기 위한 2가지 조건
1. 외부함수는 내부 함수를 반환할 것 → 외부 함수 append_string()이 내부함수 func()을 반환한다.
2. 내부 함수는 외부 함수 context에 있는 지역 변수(local variable)를 참조할 것 → 내부 함수 func()이 strings[]를 참조한다.
* 참고 : strings[] 같은 변수를 inner() 함수만이 자유롭게 접근할 수 있다고 하여 자유 변수(free variable)이라고 한다.
클로져를 사용할 수 있는 언어의 조건 2가지
1. 함수가 일급 객체(일급 시민)일 것
일급 객체란, 다음 3가지 조건을 만족하는 객체를 말한다.
- 변수나 자료구조에 저장할 수 있다.
- 함수의 매개변수로 전달할 수 있다.
- 함수의 반환값으로 사용될 수 있다.
Python에서 함수는 개체이며, 위 3가지 조건을 모두 만족하므로 일급 객체다.
2. 렉시컬 스코프(Lexical Scope)를 사용하는 언어일 것
변수의 유효한 범위를 결정하는 방법에는 크게 동적 스코프와 정적 스코프가 있다.
- 동적 스코프 : 함수가 호출된 시점에서 상위 스코프가 결정되는 방식
- 정적 스코프 : 함수가 정의된 시점에서 상위 스코프가 결정되는 방식. 렉시컬 스코프라고도 불린다.
Python은 정적 스코프를 사용한다. 아래 코드를 보자.
a = "global"
def func1():
a = "local"
func2()
def func2():
print(a)
func1()
>> global
위 코드 실행 결과 global이 출력된다. 이는 Python이 렉시컬 스코프를 사용하는 언어이기 때문이다.
func2()가 정의된 시점에서는 변수 a의 상위 스코프는 글로벌 변수의 a이기 때문에 global이 출력된다.
만약 동적 스코프를 사용하는 다른 언어라면, local이 출력될 것이다.
부분 적용(Partial Application)
Partial Application이란, 여러 인자를 갖는 함수에 대해서 특정 인자는 고정시켜주고 나머지 인자는 나중에 받는 테크닉이다. 이를 통해 함수를 재사용하고 코드를 간결하게 작성할 수 있다. 클로져 함수를 활용하면 부분 적용 어플리케이션을 구현할 수 있다.
def partial(method, level):
def wrapper(*args):
return method(level, *args) # argument forwarding
return wrapper
def log(level, content):
print(f"[{level}], {content}")
pass
err = partial(log, "ERR")
info = partial(log, "INFO")
err("Read Write failed")
info("DLL Injection Success")
파이썬에서는 partial application을 라이브러리로 제공하고 있다.
functools 라이브러리에서 partial을 import해오자.
from functools import partial
err = partial(log, "ERR")
info = partial(log, "INFO")
err("Read Write failed")
info("DLL Injection Success")
'Python' 카테고리의 다른 글
Python 연산자 오버로딩을 위한 스페셜 메서드 정리 (0) | 2024.03.29 |
---|---|
Python 패킹(packing) 언패킹(unpacking) 총정리 (0) | 2024.03.29 |
Python 제너레이터(Generator) (0) | 2024.03.29 |
Python 연결 리스트(Linked List) (0) | 2024.03.29 |
Python 싱글턴 패턴(Singleton Pattern), 반복자 패턴(Iterator Pattern), 데코레이터 패턴(Decorator Pattern) (0) | 2024.03.29 |