Nested Function in Python

What benefits or consequences can we get with Python code as follows:

class some_class(parent_class): def doOp(self, x, y): def add(x, y): return x + y return add(x, y) 

I found this in an open source project, doing something useful inside a nested function, but doing nothing outside of it except to call it. (The actual code can be found here .) Why can someone code it like this? Is there any benefit or side effect for writing code inside a nested function, and not in an external, normal function?

+60
python nested-function
Oct 19 '09 at 14:40
source share
6 answers

Usually you do this to make closures :

 def make_adder(x): def add(y): return x + y return add plus5 = make_adder(5) print(plus5(12)) # prints 17 

Internal functions can access variables from the scope (in this case, the local variable x ). If you are not accessing any variables from the scope, they are really just normal functions with a different scope.

+81
Oct 19 '09 at 16:05
source share

Besides function generators, where creating an internal function is almost the definition of a function generator, the reason I create nested functions is to improve readability. If I have a tiny function that will only be called by an external function, then I embed the definition, so you don't need to skip to determine what that function does. I can always move the internal method outside the encapsulation method if I find it necessary to reuse the function later.

Toy example:

 import sys def Foo(): def e(s): sys.stderr.write('ERROR: ') sys.stderr.write(s) sys.stderr.write('\n') e('I regret to inform you') e('that a shameful thing has happened.') e('Thus, I must issue this desultory message') e('across numerous lines.') Foo() 
+43
Oct 19 '09 at 15:03
source share

One of the potential advantages of using internal methods is that it allows you to use external variables of an external method without passing them as arguments.

 def helper(feature, resultBuffer): resultBuffer.print(feature) resultBuffer.printLine() resultBuffer.flush() def save(item, resultBuffer): helper(item.description, resultBuffer) helper(item.size, resultBuffer) helper(item.type, resultBuffer) 

can be written as follows, which is probably better read

 def save(item, resultBuffer): def helper(feature): resultBuffer.print(feature) resultBuffer.printLine() resultBuffer.flush() helper(item.description) helper(item.size) helper(item.type) 
+19
Nov 15 '12 at 12:32
source share

I can’t imagine which of the reasons for such code.

Perhaps there was a reason for the internal function in older versions, like other Ops.

For example, this has a slightly larger meaning:

 class some_class(parent_class): def doOp(self, op, x, y): def add(x, y): return x + y def sub(x,y): return x - y return locals()[op](x,y) some_class().doOp('add', 1,2) 

but instead, the inner function should be ("private")):

 class some_class(object): def _add(self, x, y): return x + y def doOp(self, x, y): return self._add(x,y) 
+8
Oct 19 '09 at 2:55
source share

The idea of ​​local methods is similar to local variables: do not pollute a larger namespace. Obviously, the benefits are limited, as most languages ​​do not provide this functionality directly.

+6
Oct 19 '09 at 14:57
source share

Are you sure the code was just that? The usual reason to do something like this is to create a partial function with baked parameters. A call to an external function returns a callable that does not need parameters, so it can be stored and used somewhere it is impossible to pass parameters. However, the code you posted will not do this - it immediately calls the function and returns the result, not the called one. It might be helpful to post the actual code you saw.

+1
Oct 19 '09 at 2:59 p.m.
source share



All Articles