예시 1 ) 중첩함수는 상위 함수 내에서 호출 및 반환 가능
def outer_func():
print('외부함수')
# 중첩 함수
def inner_func():
return '중첩함수'
print(inner_func())
# 함수에서 중첩함수 호출 가능
outer_func()
# 외부함수
# 중첩함수
예시 2 ) 중첩함수는 상위 함수 외부에서 호출 불가
def outer() :
x=100
def inner():
x=1000
return x
return x
print(outer()) # 100
print(inner())
# NameError: name 'inner' is not defined
# 상위 함수(외부 함수) 밖에서 호출 불가능
다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체
보통 아래의 연산을 지원할 때 일급 객체라고 함
예시 1 ) 함수를 변수에 할당 가능
def yell(text):
return text.upper()
# 함수를 변수에 할당
bark = yell
print(yell('python'))
# PYTHON
print(bark('python'))
# PYTHON
예시 2 ) 함수를 매개변수(parameter)로 전달 가능
def yaho(func) :
return func('yaho!')
# 함수 yell을 매개변수로 전달
print(yaho(yell))
# YAHO!
예시 3 ) 함수가 return value가 될 수 있음
def add(a,b) :
return a+b
# 함수를 return value로 사용할 수 있음
def cal(*args):
return add(*args)-3
print(cal(4,3))
# 4
위의 예시들을 통하여 파이썬에서 함수는 1급 객체라는 것을 확인할 수 있음
이러한 1급 객체의 특성이 있어야 closure가 성립
outer 함수의 안에 있으며 inner 함수의 밖에 있는 영역
자세한 내용은 여기를 참조
아래는 closure의 예시
def root_cal(number) :
def nth_root(rt):
return number**(1/rt)
return nth_root
아래의 그림과 같은 구조로 이루어져 있음
이 함수를 이용하여 계산을 진행하면 다음과 같이 진행됨
def root_cal(number) :
def nth_root(rt):
return number**(1/rt)
return nth_root
find_1000_nth_root=root_cal(1000)
print(find_1000_nth_root(2))
# 31.622776601683793
print(find_1000_nth_root(3))
# 9.999999999999998
진행 순서를 도식화 하면 다음과 같음
3 --> 4 번 순서를 지나며
root_cal(1000)의 결과가 nth_root(rt)를 return한다는 것을 저장
5번 순서를 지나며 find_1000_nth_root가 nth_root(rt)값을 받아옴을 저장
6번 순서를 지나며 rt=3
따라서 31.6228이라는 값을 return함
아래의 이미지로 위의 내용을 정리할 수 있음
global 변수를 사용하지 않아도 됨 (nonlocal 변수를 사용하기 때문에)
데이터를 숨기기 용이함
예시 )
def root_cal(number) :
def nth_root(rt):
return number**(1/rt)
return nth_root
find_1000_nth_root=root_cal(1000)
del(root_cal)
# root_cal 함수를 삭제
print(find_1000_nth_root(4))
# 5.623413251903491
위와 같이 root_cal( ) 함수를 삭제하였음에도 해당 함수를 find_1000_nth_root 함수는 사용할 수 있음
def decorator_func(other_func):
def wrapper_func():
other_func() # 다른 함수를 인자로 받음
print('그 외 other_func를 꾸며줄 내용')
return wrapper_func # 외부함수가 내부함수를 return
아래의 예시와 같이 decorator를 이용할 수 있음
예시)
def decorator_func(other_func):
def wrapper_func():
other_func() # 다른 함수를 인자로 받음
print('그 외 other_func를 꾸며줄 내용')
return wrapper_func # 외부함수가 내부함수를 return
def 적용할_함수() :
print('이 함수를 인자로 받음')
imple=decorator_func(적용할_함수)
imple()
# 이 함수를 인자로 받음
# 그 외 other_func를 꾸며줄 내용
def decorator_func(other_func):
def wrapper_func():
other_func()
print('그 외 other_func를 꾸며줄 내용')
return wrapper_func
@ decorator_func
def 적용할_함수():
print('이 함수를 인자로 받음')
# 위의 imple=decorator_func(적용할_함수)와 동일한 의미
적용할_함수()
# 이 함수를 인자로 받음
# 그 외 other_func를 꾸며줄 내용
하나의 함수에 여러개의 decorator를 적용할 수 있음
아래의 예시처럼 사용할 수 있음
예시)
def decorator1(func) :
def wrapper1(*args) :
print('Hello')
func(*args)
return wrapper1
def decorator2(func):
def wrapper2(*args) :
func(*args)
print('Nice to meet you')
return wrapper2
@decorator1
@decorator2
def other_func(name):
print(f'{name}')
other_func('Jina')
# Hello
# Jina
# Nice to meet you
만약에 name으로 여러개의 값을 받고 싶다면
def decorator1(func) :
def wrapper1(*args) :
print('Hello')
func(*args)
return wrapper1
def decorator2(func):
def wrapper2(*args) :
func(*args)
print('Nice to meet you')
return wrapper2
@decorator1
@decorator2
def other_func(*name):
print(f'{name}')
other_func('Jina','Naji')
#Hello
#('Jina', 'Naji')
#Nice to meet you
def other_func(*name) : 여기에도 args를 받는다는 표현을 해주어야함!
decorator에 parameter를 전달하고 싶을 때는
function을 감싸는 decorator를 또 감싸주고 parameter를 전달해주면 됨
아래의 예시를 참고하기
def parameter_decorator(para):
def function_decorator(func):
def wrapper(*args):
print(para)
func(*args)
return wrapper
return function_decorator
@parameter_decorator("Parameter")
def func(args):
print(f"function {args}")
func("decorator")
# Parameter
#function decorator
위의 사진을 보면 파란색으로 표시된 영역 A가 Decorator
이 데코레이터는 function을 조작하는 역할을 함
파란색 영역을 감싸고 있는 B는 A(decorator)를 중첩함수로 받아서 function에 parameter를 전달해줌
Ref
아래의 내용을 참고 및 정리
https://tech.ssut.me/python-functions-are-first-class/
https://shoark7.github.io/programming/python/closure-in-python
https://jiminsun.github.io/2018-05-07/python-closure/
https://data-flair.training/blogs/python-closure/
https://nachwon.github.io/decorator/
http://abh0518.net/tok/?p=604