title: Faking LISP-like closures in Python?
body: <p>Apologies for the unhelpful title, but I don't know how to phrase my question in a catchy one-liner. Let me therefore explain it.</p>
  
  <p>In languages like Common Lisp you can use closures to "hide global variables", as in</p>
  
  <pre><code>(let ((my-global-variable '(foo bar))))
     (defun f (x) (append my-global-variable x)))
  </code></pre>
  
  <p>The desired effect of this is that</p>
  
  <ol>
  <li>You get a variable accessible within your function that <strong>persists between function calls</strong></li>
  <li>that is <strong>invisible outside the scope of your function</strong></li>
  </ol>
  
  <p>where 'invisible' should be taken with a grain of salt since it may still be possible to access the variable from outside using implementation-dependent inspection facilities. Let us therefore agree that 'invisible' means 'does not affect the global namespace of variable'.</p>
  
  <p>One possible way to achieve 1. and 2. in Python is via:</p>
  
  <pre><code>def helper_function():
      my_global_variable = ['foo', 'bar']
      def f(x):
          return my_global_variable + x
      return f
  f = helper_function()
  </code></pre>
  
  <p>Evaluating <code>f(['baz'])</code> returns <code>['foo', 'bar', 'baz']</code> as expected, and it satisfies 1. and 2. However in contrast to the Lisp version, it is not true that</p>
  
  <ol start="3">
  <li>the variable is <strong>mutable/rebindable</strong> within the function</li>
  </ol>
  
  <p>depending on whether your using Python &lt;= 2 (no) or Python 3 (yes). Since my intent is to store in this variable a computationally expensive object, mutability is not important.
  But apart from that the above solution suffers from other problems.</p>
  
  <p>More precisely, <strong>I ask whether there is another solution</strong> that</p>
  
  <ol start="4">
  <li>is <strong>less verbose</strong></li>
  <li>and <strong>does not pollute the name space</strong> with helper objects (<code>helper_function</code> in the above example)</li>
  </ol>
  
  <p>?</p>
  
  <p>Below is a list of answers, compiled out of the helpful comments from <a href="https://stackoverflow.com/users/2357112/user2357112">user2357112</a>, <a href="https://stackoverflow.com/users/7907717/circargs">CircArgs</a>, and <a href="https://stackoverflow.com/users/1672429/stefan-pochmann">Stefan Pochmann</a>.</p>
  
  <p><strong>Solution 1: Callable Object</strong> (satisfies 1-3)</p>
  
  <pre><code>class helper_class:
      my_global_var = ['foo','bar']
      def __call__(self, x):
          return self.my_global_var + x
  f = helper_class()
  </code></pre>
  
  <p><strong>Solution 2: Default Values to Optional Arguments</strong> (satisfies 1,2,4,5 (or 2,3,4,5; see below))</p>
  
  <pre><code>def f(x, my_global_var=['foo', 'bar']):
      return my_global_var+x
  </code></pre>
  
  <p>Note that the variable <em>is mutable</em>, but mutations do not carry over between function calls, so it does not satisfy 1 and 3 simultaneously. Note also that the default argument is only evaluated once (when the function is defined), so it is acceptable for my purposes.</p>
  
  <p><strong>Solution 3: Function Attributes</strong> (satisfies 1-5)</p>
  
  <pre><code>def f(x):
      return f.my_global_var + x
  f.my_global_var = ['foo', 'bar']
  </code></pre>
  
  <p>Technically this is the best solution (at is satisfies all requirements), but it is slightly more verbose than using default arguments.</p>
  
  <p><strong>Solution 4: Clever Namespace Hack</strong> (satisfies 1,2,5)</p>
  
  <pre><code>def f():
      my_global_var = ['foo', 'bar']
      def f(x):
          return my_global_var + x
      return f
  f = f()
  </code></pre>
  
  <p>Note that the <code>f</code> being returned is really the inner and <em>not</em> the outer one.</p>