복붙노트

[PYTHON] 파이썬에서 함수를 중첩 할 때 오버 헤드가 있습니까?

PYTHON

파이썬에서 함수를 중첩 할 때 오버 헤드가 있습니까?

파이썬에서, 부모 함수 내에 자식 함수가 있다면, 부모 함수가 호출 될 때마다 자식 함수가 "초기화"(생성)됩니까? 다른 오버 헤드 내에 함수를 중첩하는 것과 관련된 오버 헤드가 있습니까?

해결법

  1. ==============================

    1.예, 매번 새로운 객체가 생성됩니다. 너가 단단한 고리 안에 있지 않으면 않는 한 그것은 문제가 아니다. 프로파일 링이 문제인지 알려줍니다.

    예, 매번 새로운 객체가 생성됩니다. 너가 단단한 고리 안에 있지 않으면 않는 한 그것은 문제가 아니다. 프로파일 링이 문제인지 알려줍니다.

    In [80]: def foo():
       ....:     def bar():
       ....:         pass
       ....:     return bar
       ....: 
    
    In [81]: id(foo())
    Out[81]: 29654024
    
    In [82]: id(foo())
    Out[82]: 29651384
    
  2. ==============================

    2.코드 오브젝트는 미리 컴파일되어 파트에 오버 헤드가 없습니다. 함수 객체는 호출 할 때마다 만들어집니다. 함수 객체를 코드 객체에 바인딩하고 기본 변수를 기록합니다.

    코드 오브젝트는 미리 컴파일되어 파트에 오버 헤드가 없습니다. 함수 객체는 호출 할 때마다 만들어집니다. 함수 객체를 코드 객체에 바인딩하고 기본 변수를 기록합니다.

    행정상 개요 : 그것은 자유롭지 않다.

    >>> from dis import dis
    >>> def foo():
            def bar():
                    pass
            return bar
    
    >>> dis(foo)
      2           0 LOAD_CONST               1 (<code object bar at 0x1017e2b30, file "<pyshell#5>", line 2>)
                  3 MAKE_FUNCTION            0
                  6 STORE_FAST               0 (bar)
    
      4           9 LOAD_FAST                0 (bar)
                 12 RETURN_VALUE 
    
  3. ==============================

    3.영향은 있지만 대부분의 상황에서는 그다지 작아서 걱정할 필요가 없습니다. 대부분의 중요하지 않은 응용 프로그램에는 이미 성능 병목 현상이있을 수 있으며 영향은 이보다 몇 배 더 큽니다. 대신 코드의 가독성과 재사용 가능성에 대해 걱정하지 않아도됩니다.

    영향은 있지만 대부분의 상황에서는 그다지 작아서 걱정할 필요가 없습니다. 대부분의 중요하지 않은 응용 프로그램에는 이미 성능 병목 현상이있을 수 있으며 영향은 이보다 몇 배 더 큽니다. 대신 코드의 가독성과 재사용 가능성에 대해 걱정하지 않아도됩니다.

    루프를 통해 매번 함수를 다시 정의하는 성능과 미리 정의 된 함수를 다시 사용하는 코드를 비교하는 코드입니다.

    import gc
    from datetime import datetime
    
    class StopWatch:
         def __init__(self, name):
             self.name = name
    
         def __enter__(self):
             gc.collect()
             self.start = datetime.now()
    
         def __exit__(self, type, value, traceback):
             elapsed = datetime.now()-self.start
             print '** Test "%s" took %s **' % (self.name, elapsed)
    
    def foo():
         def bar():
              pass
         return bar
    
    def bar2():
        pass
    
    def foo2():
        return bar2
    
    num_iterations = 1000000
    
    with StopWatch('FunctionDefinedEachTime') as sw:
        result_foo = [foo() for i in range(num_iterations)]
    
    with StopWatch('FunctionDefinedOnce') as sw:
        result_foo2 = [foo2() for i in range(num_iterations)]
    

    OS X Lion을 실행하는 Macbook Air에서 Python 2.7에서이 작업을 실행할 때 얻을 수있는 것 :

    ** Test "FunctionDefinedEachTime" took 0:00:01.138531 **
    ** Test "FunctionDefinedOnce" took 0:00:00.270347 **
    
  4. ==============================

    4.나는 이것에 대해서도 궁금해했다. 그래서 나는 얼마나 많은 오버 헤드가 발생했는지 알아보기로 결정했다. TL, DR, 대답은별로 없습니다.

    나는 이것에 대해서도 궁금해했다. 그래서 나는 얼마나 많은 오버 헤드가 발생했는지 알아보기로 결정했다. TL, DR, 대답은별로 없습니다.

    Python 3.5.2 (default, Nov 23 2017, 16:37:01) 
    [GCC 5.4.0 20160609] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> from timeit import timeit
    >>> def subfunc():
    ...     pass
    ... 
    >>> def no_inner():
    ...     return subfunc()
    ... 
    >>> def with_inner():
    ...     def s():
    ...         pass
    ...     return s()
    ... 
    >>> timeit('[no_inner() for _ in range(1000000)]', setup='from __main__     import no_inner', number=1)
    0.22971350199986773
    >>> timeit('[with_inner() for _ in range(1000000)]', setup='from __main__ import with_inner', number=1)
    0.2847519510000893
    

    필자의 본능은 percents (with_inner는 24 % 더 느리다)를 보았지만이 경우 숫자는 오해의 소지가있다. 왜냐하면 우리는 실제로 내부 함수의 값을 외부 함수에서 반환하지 않을 것이기 때문에, 특히 실제로 무엇이든합니다. 그 실수를 한 후에, 나는 이것을 다른 일반적인 일들과 비교하여 이것이 언제 그리고 중요한지를 알기로 결정했다.

        >>> def no_inner():
        ...     a = {}
        ...     return subfunc()
        ... 
        >>> timeit('[no_inner() for _ in range(1000000)]', setup='from __main__ import no_inner', number=1)
        0.3099582109998664
    

    이것을 보면 빈 dict (빠른 방법)을 만드는 것보다 시간이 덜 걸리는 것을 볼 수 있습니다. 따라서 사소한 일을하는 경우에는 전혀 문제가되지 않습니다.

  5. ==============================

    5.다른 답변은 훌륭하고 실제로 질문에 잘 대답합니다. 파이썬에서 for 루프, 함수 생성 등을 사용하여 피할 수있는 대부분의 내부 함수를 추가하고 싶습니다.

    다른 답변은 훌륭하고 실제로 질문에 잘 대답합니다. 파이썬에서 for 루프, 함수 생성 등을 사용하여 피할 수있는 대부분의 내부 함수를 추가하고 싶습니다.

    다음 예를 고려하십시오.

    def foo():
        # I need to execute some function on two sets of arguments:
        argSet1 = (arg1, arg2, arg3, arg4)
        argSet2 = (arg1, arg2, arg3, arg4)
    
        # A Function could be executed on each set of args
        def bar(arg1, arg2, arg3, arg4):
            return (arg1 + arg2 + arg3 + arg4)
    
        total =  bar(argSet1)
        total += bar(argSet2)
    
        # Or a loop could be used on the argument sets
        total = 0
        for arg1, arg2, arg3, arg4 in [argSet1, argSet2]:
            total += arg1 + arg2 + arg3 + arg4
    

    이 예는 좀 바보 같지만, 그럼에도 불구하고 내 요점을 볼 수 있기를 바랍니다. 내부 기능은 종종 필요하지 않습니다.

  6. from https://stackoverflow.com/questions/7839632/is-there-an-overhead-when-nesting-functions-in-python by cc-by-sa and MIT license