views:

182

answers:

3

I am learning Python using "Dive Into Python 3" book. I like it, but I don't understand the example used to introduce Closures in Section 6.5.

I mean, I see how it works, and I think it's really cool. But I don't see any real benefit: it seems to me the same result could be achieved by simply reading in the rules file line by line in a loop, and doing search / replace for each line read.

Could someone help me to:

  • either understand why using closures in this example improves the code (e.g., easier to maintain, extend, reuse, or debug?)

  • or suggest a source of some other real-life code examples where closures really shine?

Thank you!

+2  A: 

This might not seem particularly useful when you have access to the entire code base or when you do not have reusability in mind, but it is incredibly powerful and useful when trying to separate out logic into different, reusable modules that can be implemented in parallel by different developers. If you were to simply read the pattern strings from the file, every single module would have to be aware of this file and pass around that annoying list of pattern strings. And if you changed your system so that the pattern strings came from a URL instead of from a file, it could completely break your entire codebase. On the other hand, if you processing logic simply takes a callback function or several call back functions, and then you have another module that constructs the functions dynamically using content from a file, then only the component that constructs the functions needs to change. That is the power of being able to create functions dynamically.

Michael Aaron Safyan
Yes; but why not pass just the list of strings? One module will deal with the file or URL or whatever other input source we have. And the rest of the program will take the actual rules as a list of pattern strings.
max
@user336527, the other module can simply verify that an object meets a list of predicates. It doesn't even need to know what those predicates are. This simplifies the task of the second module, and allows it to be reused with predicates not related to string matching. Although, I will agree, the example is somewhat contrived. There are better use cases for it than the example.
Michael Aaron Safyan
Thank you, this makes things clearer to me!
max
A: 

reading in the rules file line by line in a loop ​

line by line in a loop

loop

This will drive performance through the floor. Read once, apply many times.

Ignacio Vazquez-Abrams
Sorry, I was not being very precise. Of course, I would store the pattern strings I read from the file in a list, and then always iterate through that list. But how is passing a list of functions better than passing a list of pattern strings?
max
+4  A: 

Decorators are an example of closures. For example,

def decorate(f):
    def wrapped_function():
        print("Function is being called")
        f()
        print("Function call is finished")
    return wrapped_function

@decorate
def my_function():
    print("Hello world")

my_function()

The function wrapped_function is a closure, because it retains access to the variables in its scope--in particular, the parameter f, the original function. Closures are what allow you to access it.

Closures also allow you to retain state across calls of a function, without having to resort to a class:

def make_counter():
    next_value = 0
    def return_next_value():
        nonlocal next_value
        val = next_value
        next_value += 1
        return val
    return return_next_value

my_first_counter = make_counter()
my_second_counter = make_counter()
print(my_first_counter())
print(my_second_counter())
print(my_first_counter())
print(my_second_counter())
print(my_first_counter())
print(my_second_counter())

Also, bound methods are technically closures (though they're probably implemented differently). Bound methods are class member functions with their class baked in:

import sys
w = sys.stdout.write
w("Hello\n")

w is essentially a closure with a reference to the sys.stdout object.

Finally, I havn't read that book, but a quick read of the chapter you linked and I'm very unimpressed--it's so horribly roundabout that it's useless as an explanation of closures.

Glenn Maynard
Thank you!I'd love to use a Python 3 book that is similar in style and depth to this answer, but I couldn't find one...
max