간단한 예입니다. 하나는 다른 것에서 호출되는 두 가지 방법 :
def method_a(arg):
some_data = method_b(arg)
def method_b(arg):
return some_data
파이썬에서 우리는 def
다른 것을 선언 할 수 있습니다 def
. 따라서에 method_b
필요하고 from 만 호출하는 경우 inside method_a
선언해야 합니까? 이처럼 :method_b
method_a
def method_a(arg):
def method_b(arg):
return some_data
some_data = method_b(arg)
아니면 이것을 피해야합니까?
답변
>>> def sum(x, y):
... def do_it():
... return x + y
... return do_it
...
>>> a = sum(1, 3)
>>> a
<function do_it at 0xb772b304>
>>> a()
4
이것이 당신이 찾고 있었던 것입니까? 이를 클로저 라고합니다 .
답변
실제로 이렇게하면 많은 것을 얻지 못합니다. 실제로 method_a
호출 될 때마다 다른 함수를 정의하고 다시 컴파일하기 때문에 속도가 느려집니다 . 따라서 함수 이름 앞에 밑줄을 붙여서 개인 메서드임을 나타내는 것이 _method_b
좋습니다.
중첩 된 함수의 정의가 어떤 이유로 매번 바뀌면이 작업을 수행하려고하지만 디자인의 결함을 나타낼 수 있다고 가정합니다 . 즉이 말했다 이다 중첩 함수가 외부 함수에 전달하지만, 명시 적으로 예를 들어, 함수 장식을 작성할 때 종종 발생하는 그들에게 전달되지 않은 인수를 사용할 수 있도록이 작업을 수행 할 수있는 타당한 이유가. 데코레이터를 정의하거나 사용하지 않아도 허용되는 답변에 표시되는 내용입니다.
최신 정보:
이 사소한 경우는별로 인정하지 않지만 중첩하는 것이 느리다는 것을 증명합니다 (Python 3.6.1 사용).
setup = """
class Test(object):
def separate(self, arg):
some_data = self._method_b(arg)
def _method_b(self, arg):
return arg+1
def nested(self, arg):
def method_b2(self, arg):
return arg+1
some_data = method_b2(self, arg)
obj = Test()
"""
from timeit import Timer
print(min(Timer(stmt='obj.separate(42)', setup=setup).repeat())) # -> 0.24479823284461724
print(min(Timer(stmt='obj.nested(42)', setup=setup).repeat())) # -> 0.26553459700452575
참고 나는 self
실제 함수와 비슷하게 만들기 위해 샘플 함수 에 몇 가지 인수를 추가했습니다 ( method_b2
아직 기술적으로 Test
클래스 의 메소드는 아니지만 ). 또한 중첩 함수는 실제로는 해당 버전에서 호출되지 않습니다.
답변
함수 내부의 함수는 일반적으로 클로저에 사용됩니다 .
( 클로저를 정확하게 클로저로 만드는 것에 대한 많은 논쟁 이 있습니다.)
다음은 내장을 사용하는 예입니다 sum()
. start
한 번 정의 하고 그때부터 사용합니다.
def sum_partial(start):
def sum_start(iterable):
return sum(iterable, start)
return sum_start
사용:
>>> sum_with_1 = sum_partial(1)
>>> sum_with_3 = sum_partial(3)
>>>
>>> sum_with_1
<function sum_start at 0x7f3726e70b90>
>>> sum_with_3
<function sum_start at 0x7f3726e70c08>
>>> sum_with_1((1,2,3))
7
>>> sum_with_3((1,2,3))
9
내장 파이썬 폐쇄
functools.partial
폐쇄의 예입니다.
python docs 에서 대략 다음과 같습니다.
def partial(func, *args, **keywords):
def newfunc(*fargs, **fkeywords):
newkeywords = keywords.copy()
newkeywords.update(fkeywords)
return func(*(args + fargs), **newkeywords)
newfunc.func = func
newfunc.args = args
newfunc.keywords = keywords
return newfunc
(아래 답변은 @ user225312에게 문의하십시오.이 예제는 이해하기 쉽고, @mango의 의견에 답변하는 데 도움이 될 것입니다.)
답변
일반적으로 아니요, 함수 내부에 함수를 정의하지 마십시오.
당신이 정말로 좋은 이유가 없다면 당신은하지 않습니다.
왜 안돼?
- 단위 테스트를 쉽게 수행 할 수 있습니다. 당신은 단위 테스트입니까?
- 실제로 어쨌든 완전히 난독 화하지는 않습니다 . 파이썬에서 아무것도 가정하지 않는 것이 안전합니다.
- 대신 표준 Python 자동 매직 코드 스타일 지침을 사용하여 메소드를 캡슐화하십시오.
- 당신은 될 것이다 불필요하게 동일한 코드를 사용하면 외부 함수를 실행 매번 함수 객체를 다시 .
- 함수가 정말 간단하다면 대신 표현식 을 사용해야합니다
lambda
.
함수 내부에서 함수를 정의해야하는 가장 좋은 이유 는 무엇입니까 ?
당신이 실제로 원하는 것은 딩당 폐쇄 입니다.
답변
실제로 하나의 함수를 다른 함수 안에 선언하는 것이 좋습니다. 데코레이터를 만드는 데 특히 유용합니다.
그러나 일반적으로 함수가 복잡한 경우 (10 줄 이상) 모듈 수준에서 선언하는 것이 좋습니다.
답변
중첩 된 함수를 사용하는 경우 성능에 미치는 영향에 대한 질문을하고 싶기 때문에이 질문을 찾았습니다. 쿼드 코어 2.5GHz Intel i5-2530M 프로세서가 장착 된 Windows 노트북에서 Python 3.2.5를 사용하여 다음 기능에 대한 테스트를 실행했습니다.
def square0(x):
return x*x
def square1(x):
def dummy(y):
return y*y
return x*x
def square2(x):
def dummy1(y):
return y*y
def dummy2(y):
return y*y
return x*x
def square5(x):
def dummy1(y):
return y*y
def dummy2(y):
return y*y
def dummy3(y):
return y*y
def dummy4(y):
return y*y
def dummy5(y):
return y*y
return x*x
square1, square2 및 square5에 대해서도 다음 20 회 측정했습니다.
s=0
for i in range(10**6):
s+=square0(i)
다음 결과를 얻었습니다
>>>
m = mean, s = standard deviation, m0 = mean of first testcase
[m-3s,m+3s] is a 0.997 confidence interval if normal distributed
square? m s m/m0 [m-3s ,m+3s ]
square0 0.387 0.01515 1.000 [0.342,0.433]
square1 0.460 0.01422 1.188 [0.417,0.503]
square2 0.552 0.01803 1.425 [0.498,0.606]
square5 0.766 0.01654 1.979 [0.717,0.816]
>>>
square0
중첩 함수가없고, 중첩 함수 square1
가 하나 있으며 , 중첩 함수 square2
가 2 개 이며, 중첩 함수 square5
가 5 개 있습니다. 중첩 함수는 선언되었지만 호출되지는 않습니다.
따라서 호출하지 않는 함수에 5 개의 중첩 함수를 정의한 경우 함수의 실행 시간은 중첩 함수가없는 함수의 두 배입니다. 중첩 함수를 사용할 때 조심해야한다고 생각합니다.
이 출력을 생성하는 전체 테스트의 Python 파일은 ideone 에서 찾을 수 있습니다 .
답변
노출 API에 대한 원칙 일뿐입니다.
파이썬을 사용하면 외부 공간 (모듈 또는 클래스)에서 노출 API를 피하는 것이 좋습니다. 함수는 좋은 캡슐화 장소입니다.
좋은 생각이 될 수 있습니다. 당신이 보장 할 때
- 내부 기능은 외부 기능 에서만 사용됩니다.
- 내부자 함수는 코드가 말하기 때문에 그 목적을 설명하기에 좋은 이름을 가지고 있습니다.
- 동료 또는 다른 코드 리더가 코드를 직접 이해할 수 없습니다.
그럼에도 불구하고,이 기술을 남용하면 문제가 발생할 수 있으며 설계 결함을 암시합니다.
내 특급에서 당신의 질문을 오해 할 수도 있습니다.