Nested Function, Scope 정의

제갈창민·2021년 11월 9일
0

learningbook

목록 보기
18/32

1. Nexted Function

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

    child_function()

parent_function()
"this is a child function"

-> 중첩함수(nexted function) 혹은 내부 함수는 상위 부모 함수 안에서만 호출이 가능
-> child_functionparent_function 에서만 호출 가능
-> 중첩함수를 사용하는 이유는 아래와 같다

  • 가독성
  • Closure (폐쇄)

a. 가독성

-> 함수 안의 반복되는 코드를 중첩함수로 선언하여 부모함수의 코드를 효과적으로 관리하고 가독성을 높일 수 있음

def print_all_elements(list_of_things):
    ## 중첩함수 선언
    def print_each_element(things):
        for thing in things:
            print(thing)

    if len(list_of_things) > 0:
        print_each_element(list_of_things)
    else:
        print("There is nothing!")

b. Closure(폐쇄)

-> 중첩 함수가 부모 함수의 변수나 정보를 가두어 사용하는 것
-> 부모 함수는 중첩 함수를 return함 => 부모 함수의 변수를 외부로부터 직접적인 접근을 격리하면서 중첩 함수를 통한 변수를 사용한 연산은 가능하게 함

To sum up,

  • 중첩 함수가 부모 함수의 변수나 정보를 중첩 함수 내에서 사용함
  • 부모 함수는 리턴값으로 중첩 함수를 리턴
  • 부모 함수에서 리턴했으므로 부모 함수의 변수는 직접적인 접근이 불가능 하지만 부모 함수가 리턴한 중첩 함수를 통해서 사용될 수 있음

When to use it?

-> 어떤 정보를 기반으로 연산을 실행하고 싶지만 기반이 되는 정보는 접근을 제한하여 노출이 되거나 수정이 되지 못하게 하고 싶을 때 사용함(주로 factory 패턴 구현 시)
** factory = 함수나 오브젝트를 생성해내는데 사용 됨

"input되는 수의 승 값 구하기"
def generate_power(base_number):
    def nth_power(power):
        return base_number ** power

    return nth_power

calculate_power_of_two = generate_power(2)
calculate_power_of_two(7)
>128
calculate_power_of_two(10)
>1024

calculate_power_of_seven = generate_power(7)
calculate_power_of_seven(3)
>343
calculate_power_of_seven(5)
>16907

Q. Decorator 구현하기

* Decorator는 closure처럼 중첩함수를 return 하는 함수이며, 다른 함수에 적용해서, 
적용된 함수가 실행되기 전에 무조건 실행됨(강제성 제공)
"덜 배운자의 코드덩어리"
def welcome_decorator(func):
    def decorated():
        print("Hello, ")
        func()
    return decorated

@welcome_decorator
def greeting():
    print(" welcome to WECODE!")
    return greeting

greeting()

-> 코드 발동 순서를 이해하지 못해서 입력값이 뒤집혔음
-> return은 정말 어려운 끝맺음 code다.
-> 결괏값은 두 줄이 나왔고, "Hello," 아랫줄에 "welcome to WECODE!"가 등장했다.

A.

"이것이 코드다 실전편"
def welcome_decorator(func):
   def wrapper():
      return func() + "welcome to WECODE!"   
  return wrapper

@welcome_decorator
def greeting():
    return "Hello, "

-> wrapper 가 등장했다. 저언혀 기억해내지 못한 코드라 한숨만 나올 뿐
-> 그래도 다행히 입력값의 자리가 바뀌었다는건 깨달음

Review

-> vscode 에 예제를 써놓고 몇가지 추가 예제들을 구글링해 이 값 저 값 대입해보며 또닥였더니, 그래도 많이 근접한 코드가 나왔다.
-> 아직까지 입력, 출력, 리턴값의 순서나 위치가 헷갈리고 중심이 잡히지 않은 것 같지만, repl 50번대 이후로 처음으로 내손내친 code가 답에 근접했다고 하니, 조금은 뿌듯하다.
--> 하지만 역시 갈 길이 멀다. 주말에 다 제쳐두고 함수나 요소들의 정의, 기본 개념을 싹 다시 다져놔야 할 듯하다.


2. Scope

-> 어떤 객체(변수, 함수 등)가 유효한 범위
-> 범위 순서 = [Local Scope < Enclosed < Global < Built-in]

a. Local Scope

-> 주로 함수 안에서 선언된 변수나 함수가 local scope를 가짐

b. Enclosing Scope

-> 중첩함수가 있을 때 적용되는 scope
-> 부모함수에서 선언된 변수는 중첩함수 안에서도 유효한 범위를 가지고 있음

c. Global Scope

-> 함수 밖에서 선언된 변수나 함수
-> 해당 변, 함수들은 해당 파일에서 선언된 지점 아래로는 다 유효한 범위를 가짐

d. Built-in Scope

-> 가장 광범위한 scope
-> 파이썬이 제공하는 함수 또는 속성들이 이 scope를 가짐
-> 따로 선언이 없어도 모든 파이썬 파일에서 유효한 범위를 가짐
ex> element 총 개수를 리턴하는 len 함수

e. Shadowing

-> 파이썬은 변수나 함수의 정의를 찾을 때, 다음 순서의 scope들 안에서 찾음
[Local => Enclosing => Global => Built-in]
-> 동일한 이름의 변수들이 서로 다른 scope에서 선언이 되면 더 좁은 범위에 있는 변,함수가 더 넓은 범위에 있는 변수를 가리는(shadowing) 효과가 나타남

"parameter 값에 상관 없이 무조건 "63"을 return 하기"
"아마추어의 코드 뭉치"
def scope_test(what_is_my_scope):
    number = 1
    def inner_scope_test(what_is_my_scope):
      what_is_my_scope = 63
      return number * what_is_my_scope
  
    return inner_scope_test(what_is_my_scope)
  
"프로의 코드블럭"
def scope_test(what_is_my_scope):
    what_is_my_scope = 63
    def inner_scope_test():
      return inner_scope_test
    return what_is_my_scope

-> 처음엔 곱셈을 할 생각을 않고 scope_test == 63 이라고 도배를 했지만 실패
-> 내부에 적용되는 변수랑 인자를 고정시키면 되는건가 싶어서 단순하게 1*63 구도를 만들어봄
--> 슨생님들의 고견을 여쭈었더니, 2줄이 줄어들었음
(근데 뭔가 내가 제일 처음 생각했던거랑 비슷하다. 문제는 그게 어떤식이었는지
  지금은 기억이 나지 않는다는 것임)

profile
자기계발 중인 신입 개발자

0개의 댓글