카테고리 없음

[파이썬] 중첩 함수는 Python에서 어떻게 작동합니까?

행복을전해요 2021. 1. 10. 03:10

부모 함수에서 시작된 모든 변수가 자식 함수 내부의 실제 값으로 대체되는 것을 볼 수 있습니다. 이렇게하면 자식 함수가 올바르게 실행되도록 부모 함수의 범위를 추적 할 필요가 없습니다.

"함수를 동적으로 생성"이라고 봅니다.

def maker(n):
  def action(x):
      return x ** n
        return action
        
        f = maker(2)
        --> def action(x):
        -->   return x ** 2
        

이것은 파이썬의 기본 동작이며 여러 할당으로 동일합니다.

a = 1
b = 2
a, b = b, a

파이썬은 이것을 다음과 같이 읽습니다.

a, b = 2, 1

기본적으로 값을 삽입하기 전에 값을 삽입합니다.

-------------------

기본적으로 클로저를 생성합니다 .

컴퓨터 과학에서 클로저는 어휘 환경에 묶여있는 자유 변수가있는 일류 함수입니다. 이러한 함수는 자유 변수에 "닫힌"다고합니다.

관련 자료 : 클로저 : 왜 그렇게 유용할까요?

클로저는 단순히 함수에 로컬 상태에 대한 액세스를 제공하는 더 편리한 방법입니다.

에서 http://docs.python.org/reference/compound_stmts.html :

프로그래머의 주 : 함수는 일류 객체입니다. 함수 정의 내에서 실행되는 'def'형식은 반환되거나 전달 될 수있는 로컬 함수를 정의합니다. 중첩 함수에 사용되는 자유 변수는 def를 포함하는 함수의 지역 변수에 액세스 할 수 있습니다. 자세한 내용은 이름 지정 및 바인딩 섹션을 참조하십시오.

-------------------

두 가지 기능을 정의하고 있습니다. 전화 할 때

f = maker(2)

두 배의 숫자를 반환하는 함수를 정의하고 있으므로

f(2) --> 4
f(3) --> 6

그런 다음 다른 다른 기능을 정의합니다.

g = maker(3)

그 숫자의 세 배를 반환

g(3) ---> 9

그러나 그것들은 서로 다른 두 개의 함수이며, 참조 된 동일한 함수가 아닙니다. 각각은 독립적 인 함수입니다. 스코프 내부에서도 'maker'라는 함수는 동일하게 호출되며 동일한 함수가 아니라 호출 maker()때마다 다른 함수를 정의하고 있습니다. 함수를 호출 할 때마다 동일한 이름을 사용하지만 다른 값을 포함 할 수있는 지역 변수와 같습니다. 이 경우 변수 'action'에는 함수가 포함됩니다 (다를 수 있음).

-------------------

그것이 " 클로저 " 라고 불리는 것 입니다. 간단히 말해서, 함수를 일급 객체 로 취급하는 프로그래밍 언어의 전부는 아니더라도 대부분의 경우 함수 객체 내에서 사용되는 모든 변수는 함수가 아직 살아있는 한 둘러싸여 있습니다 (즉, 기억됩니다). 사용 방법을 안다면 강력한 개념입니다.

귀하의 예에서 중첩 action함수는 변수를 사용 n하므로 해당 변수 주변에 클로저를 형성하고 나중에 함수 호출을 위해이를 기억합니다.

-------------------

내부 함수를 작성하는 세 가지 일반적인 이유를 살펴 보겠습니다.

1. 폐쇄 및 공장 기능

둘러싸는 범위의 값은 변수가 범위를 벗어나거나 함수 자체가 현재 네임 스페이스에서 제거 된 경우에도 기억됩니다.

def print_msg(msg):
    """This is the outer enclosing function"""
    
        def printer():
                """This is the nested function"""
                        print(msg)
                        
                            return printer  # this got changed
                            

이제이 함수를 호출 해 봅시다.

>>> another = print_msg("Hello")
>>> another()
Hello

이례적인 일입니다. print_msg()함수는 문자열로 불렸다 "Hello"하고 반환 된 함수는 이름에 바인드되었다 another. 을 호출 another()할 때 이미 print_msg()함수 실행을 완료했지만 메시지는 여전히 기억되었습니다 . 일부 데이터 ( "Hello")가 코드에 첨부 되는이 기술을 Python에서 클로저라고합니다.

클로저를 언제 사용합니까?

그렇다면 클로저는 무엇에 좋은가요? 클로저는 전역 값의 사용을 피할 수 있으며 데이터 숨김을 제공합니다. 또한 문제에 대한 객체 지향 솔루션을 제공 할 수 있습니다. 클래스에서 구현할 메서드가 거의 없을 때 (대부분의 경우 하나의 메서드) 클로저는 대체적이고 우아한 솔루션을 제공 할 수 있습니다. 참고

2. 캡슐화 :

캡슐화의 일반적인 개념은 외부 세계로부터 내부 세계를 숨기고 보호하는 것입니다. 여기서 내부 기능은 외부 내부에서만 액세스 할 수 있으며 기능 외부에서 일어나는 모든 일로부터 보호됩니다.

3. 건조 유지

아마도 당신은 수많은 장소에서 동일한 코드 덩어리를 수행하는 거대한 기능을 가지고있을 것입니다. 예를 들어, 파일을 처리하는 함수를 작성하고 열린 파일 객체 또는 파일 이름을 허용하려고 할 수 있습니다.

def process(file_name):
    def do_stuff(file_process):
            for line in file_process:
                        print(line)
                            if isinstance(file_name, str):
                                    with open(file_name, 'r') as f:
                                                do_stuff(f)
                                                    else:
                                                            do_stuff(file_name)
                                                            

자세한 내용은 블로그를 참조하십시오 .

-------------------

시는 기능을 만들 때 때문에 n이었다 2함수가되도록 :

def action(x):
    return x ** 2
    

f (3)을 호출하면 x이로 설정되어 3함수가3 ** 2

-------------------

사람들은 클로저에 대해 정확하게 대답했습니다. 즉, "n"내부 액션의 유효한 값은 "maker"가 호출 될 때마다 보유한 마지막 값입니다.

이를 극복하는 한 가지 쉬운 방법은 freevar (n)를 "action"함수 내에서 변수로 만드는 것입니다.이 함수는 실행되는 순간에 "n"의 복사본을받습니다.

이를 수행하는 가장 쉬운 방법은 생성 시점에 기본값이 "n"인 매개 변수로 "n"을 설정하는 것입니다. 함수의 기본 매개 변수가 함수 자체의 속성 인 튜플 (이 경우 action.func_defaults)에 저장되기 때문에이 "n"값은 고정 된 상태로 유지됩니다.

def maker(n):
    def action(x, k=n):
            return x ** k
                return action
                

용법:

f = maker(2) # f is action(x, k=2)
f(3)   # returns 3^2 = 9
f(3,3) # returns 3^3 = 27
-------------------

한 가지 용도는 매개 변수를 유지하는 함수를 반환하는 것입니다.

def outer_closure(a):
    #  parm = a               <- saving a here isn't needed
        def inner_closure():
                #return parm
                        return a              # <- a is remembered 
                            return inner_closure
                            
                            # set parm to 5 and return address of inner_closure function
                            x5 = outer_closure(5)
                            x5()
                            >5
                            
                            x6 = outer_closure(6)
                            x6()
                            >6
                            
                            # x5 inner closure function instance of parm persists 
                            x5()
                            >5
                            
-------------------

def 키워드를 사용하여 함수를 만들면 정확히 그렇게하는 것입니다. 새 함수 개체를 만들고 변수에 할당하는 것입니다. 여러분이 준 코드에서 새로운 함수 객체를 action이라는 지역 변수에 할당하고 있습니다.

두 번째로 호출하면 두 번째 함수 객체를 생성합니다. 따라서 f는 첫 번째 함수 객체 (값의 제곱)를 가리키고 g는 두 번째 함수 객체 (값의 제곱)를 가리 킵니다. 파이썬이 "f (3)"를 볼 때 그것은 "변수 f를 가리키는 함수 객체를 실행하고 값 3을 전달한다"를 의미합니다. f 및 g 및 다른 함수 객체이므로 다른 값을 반환합니다.



출처
https://stackoverflow.com/questions/2006017