중첩 기능은 파이썬에서 어떻게 작동합니까?
-
18-09-2019 - |
문제
def maker(n):
def action(x):
return x ** n
return action
f = maker(2)
print(f)
print(f(3))
print(f(4))
g = maker(3)
print(g(3))
print(f(3)) # still remembers 2
중첩 된 기능이 첫 번째 값을 기억하는 이유는 무엇입니까? 2
~ 일지라도 maker()
당시에 돌아와서 종료되었습니다 action()
호출 되나요?
해결책
부모 함수에서 발생하는 모든 변수가 어린이 함수 내부의 실제 값으로 대체되는 것으로 볼 수 있습니다. 이런 식으로, 자식 기능을 올바르게 실행하기 위해 부모 함수의 범위를 추적 할 필요가 없습니다.
"동적으로 함수 생성"으로 본다.
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
기본적으로 값을 삽입하기 전에 값을 삽입합니다.
다른 팁
당신은 기본적으로 a 폐쇄.
컴퓨터 과학에서 폐쇄는 어휘 환경에 묶인 무료 변수를 가진 일류 기능입니다. 이러한 함수는 자유 변수를 통해 "닫힙니다"라고합니다.
관련 독서 : 폐쇄 : 왜 그렇게 유용합니까?
폐쇄는 단순히 로컬 상태에 대한 기능에 액세스 할 수있는보다 편리한 방법입니다.
에서 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()
다른 기능을 정의하고 있습니다. 그것은 로컬 변수와 같습니다. 함수를 호출 할 때마다 동일한 이름을 가져 오지만 다른 값을 포함 할 수 있습니다. 이 경우 변수 '액션'에는 함수가 포함됩니다 (다를 수 있음)
내부 기능을 작성하는 세 가지 일반적인 이유를 살펴 보겠습니다.
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의 Closure라고합니다.
그렇다면 폐쇄는 무엇에 좋은가? 클로저는 글로벌 값의 사용을 피하고 일부 형태의 데이터 숨기기를 제공 할 수 있습니다. 또한 문제에 대한 객체 지향 솔루션을 제공 할 수 있습니다. 클래스에서 구현할 방법이 거의 없으면 클로저는 대체적이고 더 우아한 솔루션을 제공 할 수 있습니다. 참조
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
사람들은 폐쇄에 대해 올바르게 대답했습니다.
이를 극복하는 한 가지 쉬운 방법은 Freevar (N)를 "Action"기능 내부의 변수로 만드는 것입니다.
이를 수행하는 가장 쉬운 방법은 "n"을 창조 순간에 기본값 값의 매개 변수로 설정하는 것입니다. 함수의 기본 매개 변수가 함수 자체의 속성 인 튜플에 저장되기 때문에 "n"에 대한이 값은 고정되어 있습니다 (이 경우 action.func_defaults).
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는 첫 번째 함수 객체 (square-the-value)를 가리키고 G는 두 번째 함수 객체 (Cube-the-value)를 가리 킵니다. Python이 "F (3)"을 볼 때 "가리키는 기능 객체를 변수 f로 실행하고 값 3을 전달한다"는 의미로 사용됩니다. F와 G 및 다른 기능 객체는 다른 값을 반환합니다.