ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • TIL.43_2 Closure, Decorator, Scope (클로저, 데코레이터,스코프)
    TIL 2020. 11. 21. 15:54
    728x90

    Nested Function

    Closuer를 설명하기 전 중첩함수의 개념을 알고 있어야 이해가 가능하다.

    중첩 함수란 말그대로 함수안에 함수를 만드는 방법이다.

    중첩함수는 코드의 가독성Closure로 사용하기 위해 사용한다.

    (여기서 중첩함수는 Closure의 필요 조건이지,  충분조건이 아니다.)

    def parent_function():
        def child_function():
            print("this is a child function")
     
        child_function()
     
    parent_function()
     
    "this is a child function"

     

    Closuer

    클로저란 사전적 의미로 폐쇄 즉, 뭔가를 닫아서 가둔다는 의미가 있다.

    파이썬에서 사용하는 클로저도 외부(바깥)으로 부터 격리해 사용한다는 느낌이 크다.

    • 중첩 함수가 상위 함수의 변수/ 정보를 가두어 사용하는 것
    • 내부 함수(중첩 함수)가 외부 함수(상위 함수)의 맥락에 접근할 수 있는 것

    ( 이렇게 함수를 둘러싼 환경(지역 변수, 코드 등)을 계속 유지하다가, 

    함수를 호출할 때 다시 꺼내서 사용하는 함수를 클로저(closure)라고 한다.)

    중첩 함수가 부모 함수의 변수나 정보를 가두어 사용하는 것을 Closure라고 한다.

    그리고 부모함수는 중첩함수를 리턴해줘야한다.

    클로저를 사용하면 부모함수의 변수를 외부로부터 접근을 격리하며 중첩 함수를 통해 격리된 부모함수의 변수를 사용할 수 있게 해준다.

    간략히 위의 내용을 정리해보자

    1. 중첩함수가 부모 함수의 변수나 정보를 중첩함수 내에서 사용한다.

    2. 부모 함수는 리턴값으로 중첩 함수를 리턴한다.

    3. 부모함수에서 리턴했으므로 부모함수의 변수는 바깥에서 접근이 불가능 하지만, 부모함수가 리턴한 중첩 함수를 통해 사용 될 수 있다

    (아래에서는 부모 함수 = clac() , 중첩함수 = mul_add 이며 여기서 클로저는 = 부모함수가 된다.)

    def calc():
    	a = 3
    	b = 5
    	def mul_add(x):
    		return a * x + b # 함수 바깥쪽에 있는 지역 변수 a, b를 사용하여 계산
    	return mul_add # mul_add 함수를 반환
    
    c = calc()
    
    print(c(1), c(2), c(3), c(4), c(5))
    ::
    8 11 14 17 20

     

    Closure를 사용하는 이유

    어떠한 정보를 기반으로 연산을 실행하고 싶지만,

    기반이 되는 정보는 접근을 제한하고 노출이 되거나 수정이 되지 못하게 하고 싶을때 사용한다.

    (여기서 어떠한 정보를 중첩함수를 리턴해주는 부모함수의 역할로 만들어주면 된다.)

    1. 지역 변수와 코드를 묶어서 사용하고 싶을 때 활용한다

    2. 또한, 클로저에 속한 지역 변수는 바깥에서 직접 접근할 수 없으므로 데이터를 숨기고 싶을 때 활용.

    추가로, 클로저를 사용하면 프로그램의 흐름을 변수에 저장 할 수 있다

     

    아래 예제에서는

    calculate_power_of_two 이라는 변수를 사용해 부모 함수에 1번 접근하였음에도 불구하고

    calculate_power_of_two 는  generate_power의 지역함수 (nth_power) 연산을 계속 사용하는 것을 볼 수 있다.

    def generate_power(base_number):
        def nth_power(power):
            return base_number ** power
        return nth_power
        
    calculate_power_of_two = generate_power(2)
     # 2 설정
    
    calculate_power_of_two(7) # 2^7 값을 보여준다
    
    calculate_power_of_two(10)# 2^10
    

     

    아래 Closure에 대한 사이트를 참고하면 더 좋을것 같다.

    출처 : velog.io/@2cong/Closure

     

    Closure & Decorator

    함수 내에 선언된 함수중첩함수는 상위 함수 내에서 호출 및 반환 가능

    velog.io

     

     

    Closure 실행 과정?

    출처 : velog.io/@2cong/Closure

     

    Closure & Decorator

    함수 내에 선언된 함수중첩함수는 상위 함수 내에서 호출 및 반환 가능

    velog.io

    아래 코드의 실행 과정을 알아보자

    def root_cal(number) :
        
        def nth_root(rt):
            return number**(rt)
        
        return nth_root
    
    find_1000_nth_root=root_cal(1000)
    
    print(find_1000_nth_root(2))
    # 1000 * 1000
    
    print(find_1000_nth_root(3))
    # 1000 * 1000 * 1000

     

     

    Decorator

    • 다른 함수를 인자로 받아서 그 함수를 꾸며주는 함수

    • 외부함수가 내부함수를 return 함

    • 다른 함수를 decorator 함수의 인자로 전달

     

    Decorator 구조

    def decorator_func(other_func):
        def wrapper_func():
            other_func()   # 다른 함수를 인자로 받음
            print('그 외 other_func를 꾸며줄 내용')
          
        return wrapper_func   # 외부함수가 내부함수를 return

     

    Decorator 이용_1

    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를 꾸며줄 내용

     

    Decorator 이용_2

    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를 꾸며줄 내용

     

     

    Scope

    스코프는 범위라는 뜻으로 프로그래밍 언어에서 범위는 어떠한 객체(변수, 함수등)이 유효한 범위를 나타낸다.

    아래에서 사용되는 범위는

    전역, 지역 변수 개념에서 함께 사용되는 범위이다

     

    Local Scope (지역 범위)

    지역 변수가 접근 할 수 있는 범위를 뜻함

     

    Enclosing Scope 

    중첩함수에서 적용되는 범위

    위의 부모함수에서 할당된 hello 라는 변수는 모든 자식 함수(중첩함수)들에서 접근이 가능하다.

     

    Global Scope

    전역범위로 함수 안에서 할당이 아닌, 함수 바깥에서 할당된 전역변수가 미치는 범위로 전역범위를 의미한다.

     

    Built-in Scope

    범위 중 가장 광범위한 범위로

    파이썬 안에 내장되어 있는, 파이썬이 제공하는 함수 또는 속성들이 Built-in Scope에 해당한다.

    Built-in Scope 는 별도의 선언이 없어도 모든 파이썬 스크립트 내에서 접근이 가능하다.

    ex : len..

     

    Shadowing

    파이썬은 함수, 변수의 정의를 찾을때 아래 순서로 Scope 안에서 찾는다.

    Local => Enclosing => Global => Built-in

    만약, 동일한 이름의 변수가 서로 다른 Scope에 선언되면 더 좁은 범위에 있는 변수(함수)가 더 넓은 범위에 있는 변수(함수)를 가리는 Shadowing효과가 나타난다는 표현을 사용한다.

    이때는 global, nonlocal 등의 명령어를 통해 내부 함수에서 바깥 함수의 변수에 접근하여 변경이 가능하다.

    참고 TIL.29 codermun-log.tistory.com/69

     

    TIL. 29 전역 변수, 지역변수, 클로저 알아보기

    ## 클로저를 알기 위해서는 먼저, 함수의 사용 범위를 먼저 알아보자. ## 전역 함수와 지역 함수 ## 전역 변수 (global variable) == 위처럼 함수를 포함하여 스크립트 전체에서 접글 할 수 있는 변수를

    codermun-log.tistory.com

     

    728x90

    'TIL' 카테고리의 다른 글

    TIL.45 Database  (0) 2020.11.23
    TIL.44 과제_클래스 만들기(복기)  (0) 2020.11.22
    TIL.43 반복문 (for, while)  (0) 2020.11.21
    TIL.42_2 리스트, 튜플, 세트, 딕셔너리  (0) 2020.11.20
    TIL.42 개발자 도구 DevTools (wecode_5일차)  (0) 2020.11.20
Designed by Tistory.