"""Closures in Python. A closure consists of a lambda term (a piece of text/source code) and an "environment" that contains values of the term's FREE variables. A proper closure is therefore a lambda term that contains at least one free variable. Most modern languages support closures in some form. Functions are capable to passing closures as arguments as well as construct and return new closures. Combined with mutation (destructive assignment), closures can emulate the behavior of objects The following Javascript (node.js) function constructs and returns a closure. function make_accumulator() { // proper closures let x = 0 return (y) => { // lambda x.A in JS has form x => A x = x+y return x } } // make_accumulator let a1 = make_accumulator() let a2 = make_accumulator() console.log(a1(2)) // 2 console.log(a1(2)) // 4 console.log(a2(2)) // 2 Each closure carries its own *state* because it contains its own environment. The following program does the same in Python. The similarity with Javascript is that both are non statically-typed scripting languages. Lambda terms in python are also a bit restrictive (they can't contain multiline, arbitrary code like in JS). The declaration "nonlocal" is required to create mutable closures (closures that can change its free variables). """ def make_accumulator(): x = 0 # variable local to make_accumulator def inner(dx): nonlocal x # this keyword signals the formation of a mutable closure x = x + dx return x # end of inner function return inner # body of outer function (returns inner closure) #make_accumulator a1 = make_accumulator() a2 = make_accumulator() print(a1(2)) # prints 2 print(a1(2)) # prints 4 print(a1(3)) # prints 7 print(a2(2)) # prints 2 - a2 is a different closure. # Bank accounts using closures in Python def newaccount(name): balance = 0 def inquiry(): print(name,"has a balance of",balance) def deposit(n): nonlocal balance if n>0: balance +=n def withdraw(n): nonlocal balance if n>0 and balance-n>0: balance -= n def public_interface(request): if request=="inquiry": return inquiry() elif request=="deposit": return deposit elif request=="withdraw": return withdraw else: print("Invalid request",request) return None #public_interface return public_interface #newaccount myaccount = newaccount("Liang") youraccount = newaccount("Student") myaccount("deposit")(100) # myaccount.deposit(100), ((myaccount 'deposit) 100) youraccount("deposit")(200) youraccount("withdraw")(40) myaccount("deposit")(150) myaccount("withdraw")(50) myaccount("inquiry") youraccount("inquiry") """ But what the heck is happening in memory? This clearly won't work in C. So it must be that the values of balance and name are not just popped from the stack after newaccount exits: they somehow got moved to the heap where they can persist, and eventually get garbage collected. Let's call this "extending the lifetime" of data. Notice that we cannot, in general, determine at compile time how many times newaccount is called, thus requiring dynamic allocation. That all sounds expensive but how else can you get closures? Can closures, aka "objects" be created another way, without moving data from stack to heap without a garbage collector? Let's look at how one might solve the problem in modern C++, which has lambda terms and type inference, but C++ will never move things from stack to heap "behind the scenes". And it will never have a garbage collector. """