기능 A가 기능 B에만 필요한 경우 A를 B 내부에 정의해야합니까?
간단한 예입니다. 하나는 다른 것에서 호출되는 두 가지 방법 :
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
아니면 이것을 피해야합니까?
>>> 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
I measured the following 20 times, also for square1, square2, and square5:
s=0
for i in range(10**6):
s+=square0(i)
and got the following results
>>>
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
has no nested function, square1
has one nested function, square2
has two nested functions and square5
has five nested functions. The nested functions are only declared but not called.
So if you have defined 5 nested funtions in a function that you don't call then the execution time of the function is twice of the function without a nested function. I think should be cautious when using nested functions.
The Python file for the whole test that generates this output can be found at ideone.
It's just a principle about exposure APIs.
Using python, It's a good idea to avoid exposure API in outer space(module or class), function is a good encapsulation place.
It could be a good idea. when you ensure
- inner function is ONLY used by outer function.
- insider function has a good name to explain its purpose because the code talks.
- code cannot directly understand by your colleagues(or other code-reader).
Even though, Abuse this technique may cause problems and implies a design flaw.
Just from my exp, Maybe misunderstand your question.
So in the end it is largely a question about how smart the python implementation is or is not, particularly in the case of the inner function not being a closure but simply an in function needed helper only.
In clean understandable design having functions only where they are needed and not exposed elsewhere is good design whether they be embedded in a module, a class as a method, or inside another function or method. When done well they really improve the clarity of the code.
And when the inner function is a closure that can also help with clarity quite a bit even if that function is not returned out of the containing function for use elsewhere.
So I would say generally do use them but be aware of the possible performance hit when you actually are concerned about performance and only remove them if you do actual profiling that shows they best be removed.
Do not do premature optimization of just using "inner functions BAD" throughout all python code you write. Please.
It's perfectly OK doing it that way, but unless you need to use a closure or return the function I'd probably put in the module level. I imagine in the second code example you mean:
...
some_data = method_b() # not some_data = method_b
otherwise, some_data will be the function.
Having it at the module level will allow other functions to use method_b() and if you're using something like Sphinx (and autodoc) for documentation, it will allow you to document method_b as well.
You also may want to consider just putting the functionality in two methods in a class if you're doing something that can be representable by an object. This contains logic well too if that's all you're looking for.
mdlp's answer didn't work for me.
This did:
def some_function():
return some_other_function()
def some_other_function():
return 42
print some_function()
Do something like:
def some_function():
some_other_function()
def some_other_function():
return 42
if you were to run some_function()
it would then run some_other_function()
and returns 42.
EDIT: I originally stated that you shouldn't define a function inside of another but it was pointed out that it is practical to do this sometimes.
You can use it to avoid defining global variables. This gives you an alternative for other designs. 3 designs presenting a solution to a problem.
A) Using functions without globals
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
B) Using functions with globals
_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
C) Using functions inside another function
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
Solution C) allows to use variables in the scope of the outer function without having the need to declare them in the inner function. Might be useful in some situations.
Function In function python
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))
'programing tip' 카테고리의 다른 글
Emacs 내에서 디렉토리를 어떻게 만듭니 까? (0) | 2020.06.22 |
---|---|
Python 3.3 이상에서 패키지에 __init__.py가 필요하지 않습니까? (0) | 2020.06.22 |
지역 변수에 초기화가 필요한 이유는 무엇입니까? (0) | 2020.06.21 |
엔티티 본문없이 HTTP POST를 수행하는 것은 나쁜 습관으로 간주됩니까? (0) | 2020.06.21 |
IE9의 자리 표시 자 (0) | 2020.06.21 |