[{"data":1,"prerenderedAt":66},["ShallowReactive",2],{"qa-\u002Fpython\u002Ffunctions\u002Fclosures":3},{"page":4,"siblings":53,"blog":44},{"id":5,"title":6,"body":7,"description":11,"difficulty":14,"extension":15,"framework":16,"frameworkSlug":17,"meta":18,"navigation":19,"order":20,"path":21,"questions":22,"related":44,"seo":45,"seoDescription":46,"stem":47,"subtopic":48,"topic":49,"topicSlug":50,"updated":51,"__hash__":52},"qa\u002Fpython\u002Ffunctions\u002Fclosures.md","Closures",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"hard","md","Python","python",{},true,3,"\u002Fpython\u002Ffunctions\u002Fclosures",[23,27,32,36,40],{"id":24,"difficulty":14,"q":25,"a":26},"what-is-a-closure","What is a closure and what are free variables?","A **closure** is a nested function that **remembers variables from its\nenclosing scope** even after that outer function has returned. The\nremembered names are called **free variables** — they're neither local\nparameters nor globals. Python stores them on the function's `__closure__`\nattribute.\n\n```python\ndef multiplier(factor):\n    def multiply(n):\n        return n * factor      # 'factor' is a free variable\n    return multiply\n\ndouble = multiplier(2)\ndouble(5)                      # 10\ndouble.__closure__[0].cell_contents   # 2 — captured value\n```\n\nThe inner function keeps the binding alive via a **cell object**, which is\nwhy `multiplier` can return and `double` still works. Closures are how\nPython functions carry private state without a class.\n",{"id":28,"difficulty":29,"q":30,"a":31},"nonlocal","medium","What does the nonlocal keyword do?","By default, assigning to a name inside a function creates a **new local**.\n**`nonlocal`** tells Python that an assignment should instead **rebind a\nvariable in the nearest enclosing function scope** — letting a closure\nmutate, not just read, the captured variable.\n\n```python\ndef counter():\n    count = 0\n    def increment():\n        nonlocal count        # rebind outer 'count'\n        count += 1\n        return count\n    return increment\n\nc = counter()\nc(); c()                       # 1, then 2\n```\n\nWithout `nonlocal`, `count += 1` would raise `UnboundLocalError` (it reads\nthen assigns a local). Use `nonlocal` for enclosing-function scope and\n`global` for module scope.\n",{"id":33,"difficulty":14,"q":34,"a":35},"late-binding","Why do closures in a loop all capture the same value?","Closures capture **variables, not values** — this is **late binding**. A\nfunction created in a loop looks up the loop variable when it's *called*, not\nwhen it's defined, so every closure sees the variable's **final** value.\n\n```python\nfuncs = [lambda: i for i in range(3)]\n[f() for f in funcs]           # [2, 2, 2]  — all see final i\n\n# fix: bind the current value via a default argument\nfuncs = [lambda i=i: i for i in range(3)]\n[f() for f in funcs]           # [0, 1, 2]\n```\n\nThe default-argument trick works because **defaults are evaluated at\ndefinition time**, snapshotting `i` per iteration. A factory function that\ntakes `i` as a parameter achieves the same. This is a favorite interview\ngotcha.\n",{"id":37,"difficulty":14,"q":38,"a":39},"closure-cell","How can you inspect a closure's captured variables?","A function with free variables has a non-`None` **`__closure__`** — a tuple\nof **cell** objects, each holding one captured binding accessible via\n`cell_contents`. The matching names are listed in\n`__code__.co_freevars`. Functions with no closure have `__closure__ is\nNone`.\n\n```python\ndef make(x, y):\n    def inner():\n        return x + y\n    return inner\n\nf = make(3, 4)\nf.__code__.co_freevars               # ('x', 'y')\n[c.cell_contents for c in f.__closure__]   # [3, 4]\n```\n\nThis is mostly useful for debugging or teaching how closures actually\nstore state. The cells are shared live, so `nonlocal` rebinds are visible\nthrough `cell_contents`.\n",{"id":41,"difficulty":29,"q":42,"a":43},"closures-vs-classes","When should you use a closure instead of a class?","Both bundle **behavior with state**. A **closure** is lighter and ideal\nwhen you need a *single* method and a little hidden state. A **class** wins\nwhen you need multiple methods, inheritance, or explicit, inspectable\nstate. Common closure uses include **factories, decorators, and callbacks**.\n\n```python\n# closure: tiny stateful function\ndef make_adder(n):\n    return lambda x: x + n\nadd10 = make_adder(10)\n\n# class: equivalent but heavier\nclass Adder:\n    def __init__(self, n): self.n = n\n    def __call__(self, x): return x + self.n\n```\n\nRule of thumb: one behavior + private state → closure; many behaviors or\nshared interface → class. Decorators are the canonical real-world closure.\n",null,{"description":11},"Python interview questions on closures and free variables, __closure__, the nonlocal keyword, late binding in loops and the default-argument fix, closures vs classes, and common closure uses.","python\u002Ffunctions\u002Fclosures","Closures & Scope","Functions","functions","2026-06-18","UgESsdHC55Ja_QpbICRE7AnqAyUYkc7CLH5xgyGMyz8",[54,58,61,62],{"subtopic":55,"path":56,"order":57},"Decorators","\u002Fpython\u002Ffunctions\u002Fdecorators",1,{"subtopic":59,"path":60,"order":12},"Function Arguments","\u002Fpython\u002Ffunctions\u002Farguments",{"subtopic":48,"path":21,"order":20},{"subtopic":63,"path":64,"order":65},"Lambdas & Higher-Order Functions","\u002Fpython\u002Ffunctions\u002Flambdas",4,1781808680008]