Closures in Python
I don’t exactly make my love affair with Lisp a secret. Imperative languages are just fine, but I love me some functional programming.
I’ve recently started seriously digging into Python, though, and I think it’s
going to be the Imperative Language That Makes Me Cry The Least, at least until
I come upon something better. It’s got the holy higher-order trinity of map
,
reduce
, and filter
, syntactically sugary list comprehensions, lambda
expressions, and it even uses **
as the exponentiation operator, as God and
Fortran intended.1 It also has closures, which are magic if you
haven’t seen them before, so I’m going to yammer on about them for a bit.
To be fair, I’m probably not the best person in the world to tell you about lexical closures. You really want Wikipedia. In brief, though, a closure is a function that can access state in the scope in which it was defined. An example would probably be clearest:2
def make_power_fn(power):
def power_fn(base):
return base ** power
return power_fn
cube = make_power_fn(3)
print map(cube, [1, 2, 3, 4, 5])
Executing the above code applies our cube function to every item in the list and
prints out [1, 8, 27, 64, 125]
. Neat, right? The magic part is that cube
was
effectively able to access power
because it was defined within the enclosing
lexical scope.
The concept of closures is pretty deeply embedded in serious-business functional languages like Haskell and the various dialects of Lisp,3 but lots of relatively modern mostly imperative languages like Ruby and JavaScript have adopted them, too.
Anyway, closures! Now you know!
-
Python still can’t make “real” metaprogramming trivial the way Lisp does, though. But it’s about as good as it can be without actually being its own abstract syntax tree. ↩
-
Example adapted from defmacro’s nice functional programming discussion (near the bottom). ↩
-
“Haskell and the Lisps” would be an awesome band name, people. ↩
You might like these textually similar articles: