# Confused with Functions and decorators

Steven D'Aprano steve+comp.lang.python at pearwood.info
Sun Jul 20 08:41:08 CEST 2014

```On Sat, 19 Jul 2014 03:52:18 -0700, Jerry lu wrote:

> Ok so i am trying to learn this and i do not understand some of it. I
> also tried to searched the web but i couldnt find any answers.
>
> 1. I dont understand when i will need to use a function that returns
> another function. eg
>                    def outer():
>                          def inner():
>                                x = 5
>                           return inner
>
>      why not just use inner and forget about the whole outer function?

For the example given, there's no point in using an inner function.
(Especially since the inner function does nothing useful.) But there are
three common reasons for writing inner functions:

#1 Encapsulation and information hiding.

If you've ever programmed in Pascal, this may be familiar to you. You use
inner functions to hide them away from code outside of the function. Here
is a toy example that shows the basic idea:

def function(x):
def increment(x):
return x + 1
y = increment(x)
print x, y

In Python, I would rarely bother to write code like that. I'd just make
the increment function a top-level function, marked as "private" with a

One place where the Pascal-style nested function may be useful is with
recursive functions:

def factorial(n):
if not isinstance(n, int):
raise TypeError("n must be an integer")
if not n >= 0:
raise ValueError("n must be zero or positive")
def inner_fact(n):
if n <= 1:
return 1
return n*inner_fact(n-1)
return inner_fact(n)

* The caller cannot (easily) bypass the outer function and call the inner
function directly.

* The outer function performs all the argument checking and any pre-
processing once only, the inner function can safely assume the argument
is valid and eschew pointless error checking.

* The outer function can be renamed without breaking the recursion.

#2 Don't Repeat Yourself (DRY)

Sometimes you may have a big function that performs the same chunk of
code in two places. For example, you might write a function which
processes a file, and you want to accept either an open file object or a
file name:

def process(the_file):
def do_stuff(fp):
for line in fp:
print line
if isinstance(the_file, str):
with open(the_file, 'r') as f:
do_stuff(f)
else:
do_stuff(the_file)

Again, it is common to put do_stuff as a private top-level function, but
if you want to hide it away as an internal function, you can.

#3 Closures and factory functions

But now we come to the most important reason to use internal functions.
All of the inner functions I've shown so far have been ordinary functions
that merely happened to be nested inside another function. But when we
come to closures, that is not the case.

A closure is an inner function which "remembers" the state of its
environment when called. Here's a basic example:

def make_incrementer(inc):
"""Make an new function which increments its argument by inc.

Examples of use:

8
9

"""
def incrementer(x):
return x + inc
return incrementer

This takes more effort to explain than to write!

The "make_incrementer" function is a *factory function*. It builds a new
function each time it is called, then returns it. What does this new,
inner, function do? It takes a single argument, x, and returns x + inc.

Where does the inner function get the value of inc from? This is what
makes it a closure -- it gets the value of inc from the outer function,
the factory. How it works is something like like this:

make_incrementer(3)

=> build a function "incrementer" which takes a single argument x
=> take a snap-shot of the state of make_incrementer function
which includes inc=3
=> stuff that snap-shot into the incrementer function
=> return the incrementer function

Now, whenever you call that newly returned function, it will always see
its own private snap-shot that includes inc=3.

The use of closures and factory functions is the most common, and
powerful, use for inner functions. 9 times out of 10, if you see a
decoratored function:

@decorator
def func(arg):
pass

the decorator is a factory function which takes an function as argument,
and returns a new function which which includes the old function inside
the closure. But that's now getting into more advanced territory.

> 2. This is more yes or no question when you pass in a func into another
> func as a parameter do you need to specify the parameter that the func
> is being passed into as func?

No.

You can pass functions around from place to place until the cows come
how, stuff them into lists and dicts, extract them again, and not care
one iota about its arguments until you actually call it.

--
Steven

```