programing

중첩 함수는 하나의 함수에만 필요할 때 좋은 접근 방식입니까?

newsource 2023. 7. 19. 21:23

중첩 함수는 하나의 함수에만 필요할 때 좋은 접근 방식입니까?

예를 들면,function A는 에의서필다니요합만해만 필요합니다.function BA는 B 안에서 정의되어야 합니까?

간단한 예입니다.두 가지 방법, 하나는 다른 방법에서 호출됩니다.

def method_a(arg):
    some_data = method_b(arg)

def method_b(arg):
    return some_data

에서 우리는 을 선언할 수 있습니다.def 인타내에의 에.def그래서 만약에method_b됩니다.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은 엄밀히 ▁of▁the▁method다▁still의 방법이 아닙니다.Test 중첩 는 당신의버전과 됩니다.또한 중첩 함수는 사용자의 버전과 달리 해당 버전에서 실제로 호출됩니다.

일반적으로 아니요, 함수 내부의 함수는 정의하지 않습니다.

당신이 정말로 좋은 이유가 없다면요.당신이 모르는 것.

왜 안 되나요?

함수 내부의 함수를 정의하는 정말 좋은 이유는 무엇입니까?

당신이 실제로 원하는 것이 딩당 폐쇄일 때.

함수 내부의 함수는 일반적으로 폐쇄에 사용됩니다.

(정확히 무엇마감을 마감하게 하는지에 대해 많은 논쟁이 있습니다.)

다음은 기본 제공 기능을 사용한 예입니다.정의합니다.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 문서에서 보면 대략 다음과 같습니다.

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의 의견에 답하는 데 도움이 될 것입니다.)

실제로 한 기능을 다른 기능 안에 선언해도 괜찮습니다.이것은 특히 장식가를 만드는 데 유용합니다.

그러나 함수가 복잡한 경우(10줄 이상) 모듈 수준에서 선언하는 것이 경험상 더 나은 방법일 수 있습니다.

중첩 함수를 사용하면 성능에 영향을 미치는 이유에 대해 질문하고 싶어서 이 질문을 발견했습니다.Quad Core 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

제곱 1, 제곱 2, 제곱 5에 대해서도 다음을 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에는 두 함수와 두 개 있 습 다 니 함가수중첩이 있습니다.square5에는 5개의 중첩 함수가 있습니다.중첩 함수는 선언될 뿐 호출되지 않습니다.

따라서 호출하지 않는 함수에 중첩 함수를 5개 정의한 경우 함수의 실행 시간은 중첩 함수가 없는 함수의 두 배입니다.중첩 함수를 사용할 때는 주의해야 한다고 생각합니다.

이 출력을 생성하는 전체 테스트의 Python 파일은 ideone에서 찾을 수 있습니다.

그래서 결국 파이썬 구현이 얼마나 똑똑한지에 대한 질문이 많습니다. 특히 내부 함수가 폐쇄가 아니라 단순히 기능이 없는 도우미만 필요한 경우입니다.

기능이 필요한 곳에만 있고 다른 곳에 노출되지 않는 깨끗한 이해 가능한 설계는 모듈, 방법으로서의 클래스, 또는 다른 기능이나 방법 내부에 포함된 경우에도 좋은 설계입니다.잘만 되면 코드의 명확성이 향상됩니다.

그리고 내부 기능이 다른 곳에서 사용하기 위해 포함된 기능에서 해당 기능이 반환되지 않더라도 명확성에 상당히 도움이 될 수 있는 폐쇄 기능일 때.

따라서 일반적으로 이러한 기능을 사용하지만 실제로 성능에 관심이 있을 때는 성능에 영향을 미칠 수 있다는 것을 알고 제거하는 것이 가장 좋다는 것을 보여주는 실제 프로파일링을 수행할 때만 이러한 기능을 제거할 수 있습니다.

작성하는 모든 파이썬 코드에서 "내부 함수 BAD"를 사용하는 것에 대한 조기 최적화를 수행하지 마십시오.부탁합니다.

노출 API에 대한 원칙일 뿐입니다.

파이썬을 사용하여 외부 공간(모듈 또는 클래스)에서 노출 API를 피하는 것이 좋습니다. 함수는 캡슐화하기 좋은 장소입니다.

좋은 생각일 수도 있어요.확실한 경우에

  1. 내부 기능은 외부 기능에서만 사용됩니다.
  2. 내부 함수는 코드가 말하기 때문에 목적을 설명하기에 좋은 이름을 가지고 있습니다.
  3. 코드는 동료(또는 다른 코드 변환자)가 직접 이해할 수 없습니다.

그러나 이 기법을 악용하면 문제가 발생할 수 있으며 설계 결함이 발생할 수 있습니다.

내 전처에서 들은 바로는, 아마 당신의 질문을 오해했을 것입니다.

그런 식으로 하는 것은 완벽하게 괜찮지만, 클로저를 사용하거나 기능을 반환해야 하는 경우가 아니라면 모듈 레벨에 넣었을 것입니다.두 번째 코드 예제에서는 다음을 의미한다고 생각합니다.

...
some_data = method_b() # not some_data = method_b

그렇지 않으면 some_data가 함수가 됩니다.

모듈 수준에서 사용하면 다른 함수가 method_b()를 사용할 수 있으며, 문서화를 위해 스핑크스(및 자동 문서)와 같은 것을 사용하는 경우 method_b도 문서화할 수 있습니다.

또한 객체로 표현할 수 있는 작업을 수행하는 경우 클래스에서 두 가지 방법으로 기능을 배치하는 것도 고려해 볼 수 있습니다.이것이 당신이 찾고 있는 전부라면 논리도 잘 포함되어 있습니다.

글로벌 변수를 정의하지 않기 위해 사용할 수 있습니다.이렇게 하면 다른 설계에 대한 대안을 얻을 수 있습니다. 문제에 대한 해결책을 제시하는 세 가지 설계입니다.

전역 없이 함수 사용

def calculate_salary(employee, list_with_all_employees):
    x = _calculate_tax(list_with_all_employees)

    # some other calculations done to x
    pass

    y = # something 

    return y

def _calculate_tax(list_with_all_employees):
    return 1.23456 # return something

글로벌 기능 사용

_list_with_all_employees = None

def calculate_salary(employee, list_with_all_employees):

    global _list_with_all_employees
    _list_with_all_employees = list_with_all_employees

    x = _calculate_tax()

    # some other calculations done to x
    pass

    y = # something

    return y

def _calculate_tax():
    return 1.23456 # return something based on the _list_with_all_employees var

다른 함수 내부의 함수 사용

def calculate_salary(employee, list_with_all_employees):

    def _calculate_tax():
        return 1.23456 # return something based on the list_with_a--Lemployees var

    x = _calculate_tax()

    # some other calculations done to x
    pass
    y = # something 

    return y

솔루션 C)에서는 변수를 내부 함수에 선언할 필요 없이 외부 함수의 범위에서 사용할 수 있습니다.상황에 따라 유용할 수 있습니다.

다음과 같은 작업 수행:

def some_function():
    return some_other_function()
def some_other_function():
    return 42 

만약 당신이 도망친다면some_function()그러면 실행됩니다.some_other_function()그리고 42를 반환합니다.

편집: 저는 원래 다른 기능의 내부를 정의해서는 안 된다고 말했지만, 때때로 이것을 하는 것이 실용적이라는 지적이 있었습니다.

함수 인 함수 파이썬

def Greater(a,b):
    if a>b:
        return a
    return b

def Greater_new(a,b,c,d):
    return Greater(Greater(a,b),Greater(c,d))

print("Greater Number is :-",Greater_new(212,33,11,999))

언급URL : https://stackoverflow.com/questions/4831680/is-nested-function-a-good-approach-when-required-by-only-one-function