As mgilson and Neal the most straightforward way of doing this is to use a default argument when you define f
.
A bigger issue is the philosophical mismatch here. Python does closures, but they're going to operate differently than you expect from SML (which I'm not particularly familiar with) or Haskell or Clojure or something (both of which I'm more familiar with). This is because of the way Python handles closures, but also because of the way it defines anonymous functions differently and allows side-effects.
Typically, where functional approaches don't work well, in Python you use a class, in this case to capture the value of x.
class F(object):
def __init__(self, x):
self.x = x
def __call__(self):
return self.x
x = 3
f = F(x)
f()
# 3
x = 7
f()
# 3
This is way, way overkill for this example, and I obviously wouldn't recommend it here. But often in Python, the answer is to use a class. (That is a gross over-statement, and my brain's spawning exceptions faster than I can type them. But when you're coming from a functional background, I think that this statement is a good heuristic as you're learning to approach problems Pythonically.)
As an aside, it's also interesting that this makes explicit what capturing the variable in the function argument definition does implicitly: it creates a function object that hangs onto the value of x
at the point the object is created.