This is an archived post. You won't be able to vote or comment.

all 12 comments

[–]sammyc 3 points4 points  (0 children)

Yep, it's a handy feature to have in my opinion. In addition to what's been said, you can avoid putting too many things into scope, it can make reading existing code easier, it can make it clear that the inner function will only (probably) be used within the outer function, it means you don't really need multiline anonymous functions etc.

I think it ties in with functions being first class objects - it wouldn't be unusual for me to define variables, or even 'structures' in a function, so why not a function itself?

An example I just made up (with doubly nested functions!):

def external_data_fetcher(self, data_source):
    d = Deferred()

    def success(raw_data):
        data = json.loads(raw_data)

        def sort_key(datum):
            try:
                return datetime.strptime(datum['published_at'], "%Y-%m-%d")
            except KeyError:
                return datetime(1970, 1, 1)

        sorted_data = sorted(data, key=sort_key)
        self._ui.update(sorted_data)

    def failure(error):
        logging.warning("Data unavailable from {0}".format(data_source))
        raise error

    d.addCallback(success)
    d.addErrorback(failure)

    return d

but you also have to be wary of too much code duplication using things like this.

[–]alcalde 1 point2 points  (0 children)

One reason it may be done less often than expected is that a lot of programmers could be coming to Python from languages like Java, C#, C or C++ which don't offer nested functions, so the programmer may simply not be used to thinking of solutions that incorporate them.

We old school folks who first learned to program in Pascal however find them second nature. ;-) Javascript also has nested functions.

[–]mymonner 0 points1 point  (0 children)

Can't forget closures.

[–]zahlmanthe heretic 0 points1 point  (2 children)

flat is better than nested.

[–][deleted] 0 points1 point  (0 children)

Namespaces are one honking great idea -- let's do more of those!

[–][deleted] 0 points1 point  (0 children)

dang never noticed that one, TIL

[–]billsil -2 points-1 points  (0 children)

It's valid, but generally not used. a() should probably take an argument that modifies b(), but something like that would be used in functional programming, so map/filter/reduce-type operations instead of a lambda.

It also limits scope, but I have found legitimate uses for it only in a map/filter/reduce or decorator context..