[{"data":1,"prerenderedAt":70},["ShallowReactive",2],{"qa-\u002Fpython\u002Ffundamentals\u002Fscope-legb":3},{"page":4,"siblings":52,"blog":43},{"id":5,"title":6,"body":7,"description":11,"difficulty":14,"extension":15,"framework":16,"frameworkSlug":17,"meta":18,"navigation":19,"order":12,"path":20,"questions":21,"related":43,"seo":44,"seoDescription":45,"stem":46,"subtopic":47,"topic":48,"topicSlug":49,"updated":50,"__hash__":51},"qa\u002Fpython\u002Ffundamentals\u002Fscope-legb.md","Scope Legb",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"medium","md","Python","python",{},true,"\u002Fpython\u002Ffundamentals\u002Fscope-legb",[22,26,30,35,39],{"id":23,"difficulty":14,"q":24,"a":25},"legb-rule","What is the LEGB rule?","**LEGB** describes the order Python searches for a name: **Local** (inside the\ncurrent function), **Enclosing** (any outer functions), **Global** (the module's\ntop level), then **Built-in** (names like `len`, `print`). The first match wins,\nand the search stops there.\n\n```python\nx = \"global\"\ndef outer():\n    x = \"enclosing\"\n    def inner():\n        x = \"local\"\n        print(x)     # \"local\"  — Local found first\n    inner()\nouter()\n```\n\nWhy it matters: nearly every \"why is this variable that value?\" question reduces\nto walking **L -> E -> G -> B** until a name is found.\n",{"id":27,"difficulty":14,"q":28,"a":29},"global-vs-nonlocal","What is the difference between `global` and `nonlocal`?","Both let you **rebind** a name from an outer scope instead of creating a new local.\n`global` targets the **module-level** name; `nonlocal` targets the **nearest\nenclosing function** scope (and that name must already exist there).\n\n```python\ncount = 0\ndef inc():\n    global count\n    count += 1        # rebinds module-level count\n\ndef outer():\n    x = 1\n    def inner():\n        nonlocal x\n        x = 2          # rebinds outer's x, not a new local\n    inner()\n    return x           # 2\n```\n\nRule of thumb: you only need these keywords to **reassign** an outer name — you can\nalways *mutate* an outer mutable object (e.g. `list.append`) without them.\n",{"id":31,"difficulty":32,"q":33,"a":34},"unbound-local-error","hard","Why does assigning to a name make it local and cause UnboundLocalError?","Python decides a name's scope **at compile time** by scanning the whole function\nbody. If a name is **assigned anywhere** in a function, it is treated as **local\nfor the entire function** — even on lines before the assignment. Reading it before\nit's bound raises **UnboundLocalError**.\n\n```python\nx = 10\ndef f():\n    print(x)      # UnboundLocalError: x is local because of the line below\n    x = 20        # this assignment makes x local everywhere in f\n```\n\nThe fix is to declare `global x` (or `nonlocal x`) if you meant the outer name, or\nsimply read a different name. Rule of thumb: **an assignment anywhere makes the\nname local everywhere** in that function.\n",{"id":36,"difficulty":32,"q":37,"a":38},"late-binding-closures","Why do closures in a loop all capture the same value?","Closures capture **variables, not values** — this is **late binding**. The inner\nfunction looks up the loop variable **when it is called**, by which time the loop\nhas finished and the variable holds its final value.\n\n```python\nfuncs = [lambda: i for i in range(3)]\n[f() for f in funcs]      # [2, 2, 2]  — all see the 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 captures `i`'s value at definition time. Rule of thumb:\nif loop-created closures behave strangely, you're hitting late binding — bind the\nvalue explicitly.\n",{"id":40,"difficulty":14,"q":41,"a":42},"module-vs-function-shadowing","How does name shadowing work between module and function scope?","A local name **shadows** (hides) an outer name of the same identity for the\nduration of the scope. Assigning to it inside a function creates a separate local\nthat leaves the **module-level** name untouched.\n\n```python\nvalue = \"module\"\ndef f():\n    value = \"function\"   # new local — shadows the global\n    print(value)         # \"function\"\nf()\nprint(value)             # \"module\"  — unchanged\n\nlist = [1, 2]            # shadows the built-in list() in this scope!\n```\n\nWatch out for shadowing **built-ins** (`list`, `id`, `sum`, `type`) — it silently\nbreaks later calls. Rule of thumb: keep names distinct from outer scopes and\nbuilt-ins to avoid surprising lookups.\n",null,{"description":11},"Python interview questions on the LEGB scope rule, global vs nonlocal, UnboundLocalError, late binding in loop closures, and name shadowing.","python\u002Ffundamentals\u002Fscope-legb","Variables, Scope & the LEGB Rule","Fundamentals","fundamentals","2026-06-18","Dpt_Q0OFjMvd7AoVKH6T5OWFzpQa5ln0EU8zsuvK55I",[53,57,58,62,66],{"subtopic":54,"path":55,"order":56},"Mutability & Data Types","\u002Fpython\u002Ffundamentals\u002Fmutability",1,{"subtopic":47,"path":20,"order":12},{"subtopic":59,"path":60,"order":61},"Numbers & Operators","\u002Fpython\u002Ffundamentals\u002Fnumbers-operators",3,{"subtopic":63,"path":64,"order":65},"Strings & String Formatting","\u002Fpython\u002Ffundamentals\u002Fstrings-formatting",4,{"subtopic":67,"path":68,"order":69},"Truthiness & Type Conversion","\u002Fpython\u002Ffundamentals\u002Ftruthiness-conversion",5,1781808679263]