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개의 댓글

관련 채용 정보

Powered by GraphCDN, the GraphQL CDN