Closures in Python
A closure is data attached to code (pretty simple, eh?). I use them for:
Ceder's The Quick Python Book uses a closure as part of the @decorator pattern (section 9.8).
Here is a closure in python:
Caveats
In some languages, the variable bindings contained in a closure behave just like any other variables. Alas, in python they are read-only. This is similar to Java, and has the same solution: closing container objects. Closure of a dictionary or array won't let you assign a new dictionary or array, but will let you change the contents of the container. This is a common use pattern - every time you set a variable on self, you are changing the contents of a closed dictionary.
- Replacing hard coded constants
- Eleminating globals
- Providing consistent function signatures
- Implementing Object Orientation
Ceder's The Quick Python Book uses a closure as part of the @decorator pattern (section 9.8).
Here is a closure in python:
def makeInc(x):Closures in python are created by function calls. Here, the call to makeInc creates a binding for x that is referenced inside the function inc. Each call to makeInc creates a new instance of this function, but each instance has a link to a different binding of x. The example shows the closure of x being used to eliminate either a global or a constant, depending on the nature of x.
def inc(y):
# x is "closed" in the definition of inc
return y + x
return inc
inc5 = makeInc(5)
inc10 = makeInc(10)
inc5 (5) # returns 10
inc10(5) # returns 15
import timeIn python, all methods (but not functions) are closures ... sort of. The method definition foo.update closes the class foo. The value of g.update is a closure that stores the value of g and passes that as the first argument of foo.self, hence the first argument of a method in python is self. Details aside, it is important to note that the designers of python have gone out of their way so that you can pass g.update by itself to another function and have it continue to work correctly.
keepRunning = True
updates = []
def runLoop():
while (keepRunning):
for u in updates:
u()
class foo:
def __init__(self, x = 0):
self.x = x
def update(self):
print self.x
self.x += 1
f = foo()
g = foo(2)
updates.extend([f.update, g.update])
Caveats
In some languages, the variable bindings contained in a closure behave just like any other variables. Alas, in python they are read-only. This is similar to Java, and has the same solution: closing container objects. Closure of a dictionary or array won't let you assign a new dictionary or array, but will let you change the contents of the container. This is a common use pattern - every time you set a variable on self, you are changing the contents of a closed dictionary.
7 Comments:
In my freshman year at GaTech, a lecturer told me that not being able to treat functions (or "methods" have you) in Java wasn't a problem, and one day I'd realize it. For a moment, I foolishly believed him, only knowing functions as function arguments or return values from their mind-warping manifestation in C.
If that lecturer only one day discovers ... it IS a problem. The strict OOP style of modeling functions is sheer fraud! Raaahhh, let there be callables and partial evaluation!
By djfroofy, At 8/14/07 1:23 PM
Am I missing something or should the above NOT work? Shouldn't you get something like:
TypeError: update() takes no arguments (1 given)
if you try to run it?
By Tim, At 5/19/09 7:45 AM
Tim: Good catch! In the almost two years this post has been up, no one has pointed that out! I've edited the post so that update now takes the argument "self".
By ynniv, At 5/19/09 12:07 PM
> Tim: Good catch! In the almost two years this post has been up, no one has pointed that out!
wow you didn't even test that little bits of code before showing to the world.
c'mon you know better than like. have a little discipline, sheeesh.
sorry, just my pet peeve....tired of seeing people (especially book authors) putting out untested crap.
By Matelot, At 11/13/09 12:31 AM
sorry, just my pet peeve....tired of seeing people (especially book authors) putting out untested crap.
LOL
By Anonymous, At 12/17/09 11:22 PM
>Closures in python are created by function calls.
Thank you! This solved a problem I spent the last two hours trying to solve.
By nick.cash, At 3/24/10 4:01 PM
It's a blog. You're allowed to make mistakes, act hastily, and punch people wearing glasses in the face.
What you are NOT allowed to do is criticize someone with a pissant response full of spelling and grammatical errors.
Pot meet kettle.
ps. Great article ynniv. Linked in from diveintopython3.org
By Anonymous, At 4/1/10 10:08 PM
Post a Comment
<$I18N$LinksToThisPost>:
Create a Link
<< Home