{"id":1479,"date":"2011-01-31T21:17:11","date_gmt":"2011-02-01T05:17:11","guid":{"rendered":"http:\/\/blog.mozilla.org\/webdev\/?p=1479"},"modified":"2011-02-12T22:02:24","modified_gmt":"2011-02-13T06:02:24","slug":"python-scoping-understanding-legb","status":"publish","type":"post","link":"https:\/\/blog.mozilla.org\/webdev\/2011\/01\/31\/python-scoping-understanding-legb\/","title":{"rendered":"Python scoping: understanding LEGB"},"content":{"rendered":"<p><em>Note: this is a repost from my blog. You can find the original post <a href=\"http:\/\/embrangler.com\/2011\/01\/python-scoping-understading-legb\/\">here.<\/a><\/em><br \/>\n<strong>Update:<\/strong> Thanks to Avazu for <a href=\"#clean-suggestion\">a clean suggestion<\/a> and Fred for pointing out I should have indicated a good way to get around this.<\/p>\n<h2>Summary<\/h2>\n<p>Python scoping fun! <a href=\"http:\/\/stackoverflow.com\/questions\/291978\/short-description-of-python-scoping-rules\">Read about LEGB<\/a> to understand the basics of python scoping.<\/p>\n<h2>Beef<\/h2>\n<p>I never bothered to read about how python scoping works until I hit this. It\u2019s not exactly something to research until you have issues with it. \ud83d\ude42<\/p>\n<p>I had something like this going on:<br \/>\n<code><\/p>\n<pre>\r\ndef func1(param=None):\r\n    def func2():\r\n        if not param:\r\n            param = 'default'\r\n        print param\r\n    # Just return func2.\r\n    return func2\r\n\r\n\r\nif __name__ == '__main__':\r\n   func1('test')()\r\n<\/pre>\n<p><\/code><br \/>\n<strong>Note:<\/strong> Actual code was not as straightforward, <code>func2<\/code> was actually a decorator. Admittedly, using the same parameter name is not a must, but it\u2019s still a curiosity. I just wanted to fall back to a default value on run-time.<\/p>\n<p>If you try to run this in python, here\u2019s what you get:<br \/>\n<code><\/p>\n<pre>\r\n~ $ python test.py \r\nTraceback (most recent call last):\r\n  File \"test.py\", line 11, in <module>\r\n    func1('test')()\r\n  File \"test.py\", line 3, in func2\r\n    if not param:\r\nUnboundLocalError: local variable 'param' referenced before assignment\r\n<\/pre>\n<p><\/code><\/p>\n<p>If you\u2019re curious, you can <a href=\"http:\/\/stackoverflow.com\/questions\/291978\/short-description-of-python-scoping-rules\">read about the principles of LEGB.<\/a> You have to understand a bit about compilers and <a href=\"http:\/\/en.wikipedia.org\/wiki\/Abstract_syntax_tree\">the AST<\/a> to get what\u2019s going on behind the scenes. You might think that replacing lines 3-4 with:<br \/>\n<code><\/p>\n<pre>\r\nparam = param or 'default'\r\n<\/pre>\n<p><\/code><\/p>\n<p>Might work. But no. You can\u2019t assign the same parameter at the local level if the enclosing level defines it. Even this fails:<br \/>\n<code><\/p>\n<pre>\r\nparam = param\r\n<\/pre>\n<p><\/code><\/p>\n<p>Fun, no?<\/p>\n<h2 id=\"clean-suggestion\">What to do?<\/h2>\n<p>There are a few ways to get around this.<\/p>\n<ul>\n<li>Assign <code>param<\/code> outside of func2. This doesn&#8217;t work if you need the default value to be dependent on what params func2 receives.<\/li>\n<li>Use a second variable, <code>param2<\/code> inside of func2 (posted below).<\/li>\n<\/ul>\n<p>Here is the solution suggested by our commenter Avazu:<br \/>\n<code><\/p>\n<pre>\r\ndef func1(param=None):\r\n    def func2(param2=param):\r\n        if not param2:\r\n            param2 = 'default'\r\n        print param2\r\n    # Just return func2.\r\n    return func2\r\n<\/pre>\n<p><\/code><\/p>\n<h2>Read more<\/h2>\n<ul>\n<li><a href=\"http:\/\/stackoverflow.com\/questions\/291978\/short-description-of-python-scoping-rules\">LEGB (stackoverflow)<\/a><\/li>\n<li><a href=\"http:\/\/docs.python.org\/tutorial\/classes.html#python-scopes-and-namespaces\">Python docs on scope and namespaces.<\/a><\/li>\n<\/ul>\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Note: this is a repost from my blog. You can find the original post here. Update: Thanks to Avazu for a clean suggestion and Fred for pointing out I should have indicated a good way to get around this. Summary &hellip; <a class=\"go\" href=\"https:\/\/blog.mozilla.org\/webdev\/2011\/01\/31\/python-scoping-understanding-legb\/\">Continue reading<\/a><\/p>\n","protected":false},"author":211,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4712],"tags":[],"coauthors":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v22.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Python scoping: understanding LEGB - Mozilla Web Development<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/blog.mozilla.org\/webdev\/2011\/01\/31\/python-scoping-understanding-legb\/\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Paul Craciunoiu\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"2 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/blog.mozilla.org\/webdev\/2011\/01\/31\/python-scoping-understanding-legb\/\",\"url\":\"https:\/\/blog.mozilla.org\/webdev\/2011\/01\/31\/python-scoping-understanding-legb\/\",\"name\":\"Python scoping: understanding LEGB - Mozilla Web Development\",\"isPartOf\":{\"@id\":\"https:\/\/blog.mozilla.org\/webdev\/#website\"},\"datePublished\":\"2011-02-01T05:17:11+00:00\",\"dateModified\":\"2011-02-13T06:02:24+00:00\",\"author\":{\"@id\":\"https:\/\/blog.mozilla.org\/webdev\/#\/schema\/person\/e5959c8c5a38805891ed2bd45e2f8d0c\"},\"breadcrumb\":{\"@id\":\"https:\/\/blog.mozilla.org\/webdev\/2011\/01\/31\/python-scoping-understanding-legb\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/blog.mozilla.org\/webdev\/2011\/01\/31\/python-scoping-understanding-legb\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/blog.mozilla.org\/webdev\/2011\/01\/31\/python-scoping-understanding-legb\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/blog.mozilla.org\/webdev\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Python scoping: understanding LEGB\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/blog.mozilla.org\/webdev\/#website\",\"url\":\"https:\/\/blog.mozilla.org\/webdev\/\",\"name\":\"Mozilla Web Development\",\"description\":\"For make benefit of glorious tubes\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/blog.mozilla.org\/webdev\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/blog.mozilla.org\/webdev\/#\/schema\/person\/e5959c8c5a38805891ed2bd45e2f8d0c\",\"name\":\"Paul Craciunoiu\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/blog.mozilla.org\/webdev\/#\/schema\/person\/image\/bcf0b623715b0faf8c35c90d58d6acd6\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/605bb18eedd69211a2a5783afe9a5ad6?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/605bb18eedd69211a2a5783afe9a5ad6?s=96&d=mm&r=g\",\"caption\":\"Paul Craciunoiu\"},\"description\":\"I'm a full time web developer for Mozilla, with main focus on Django, Python, and JavaScript. I have a B.S.C.S. from UCSC. I\u2019ve been involved with Mozilla since 2008. If you're interested in more about me and what I do, check out my blog or follow me on twitter.\",\"sameAs\":[\"http:\/\/embrangler.com\"],\"url\":\"https:\/\/blog.mozilla.org\/webdev\/author\/paulc-2\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Python scoping: understanding LEGB - Mozilla Web Development","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/blog.mozilla.org\/webdev\/2011\/01\/31\/python-scoping-understanding-legb\/","twitter_misc":{"Written by":"Paul Craciunoiu","Est. reading time":"2 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/blog.mozilla.org\/webdev\/2011\/01\/31\/python-scoping-understanding-legb\/","url":"https:\/\/blog.mozilla.org\/webdev\/2011\/01\/31\/python-scoping-understanding-legb\/","name":"Python scoping: understanding LEGB - Mozilla Web Development","isPartOf":{"@id":"https:\/\/blog.mozilla.org\/webdev\/#website"},"datePublished":"2011-02-01T05:17:11+00:00","dateModified":"2011-02-13T06:02:24+00:00","author":{"@id":"https:\/\/blog.mozilla.org\/webdev\/#\/schema\/person\/e5959c8c5a38805891ed2bd45e2f8d0c"},"breadcrumb":{"@id":"https:\/\/blog.mozilla.org\/webdev\/2011\/01\/31\/python-scoping-understanding-legb\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/blog.mozilla.org\/webdev\/2011\/01\/31\/python-scoping-understanding-legb\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/blog.mozilla.org\/webdev\/2011\/01\/31\/python-scoping-understanding-legb\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/blog.mozilla.org\/webdev\/"},{"@type":"ListItem","position":2,"name":"Python scoping: understanding LEGB"}]},{"@type":"WebSite","@id":"https:\/\/blog.mozilla.org\/webdev\/#website","url":"https:\/\/blog.mozilla.org\/webdev\/","name":"Mozilla Web Development","description":"For make benefit of glorious tubes","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/blog.mozilla.org\/webdev\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/blog.mozilla.org\/webdev\/#\/schema\/person\/e5959c8c5a38805891ed2bd45e2f8d0c","name":"Paul Craciunoiu","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/blog.mozilla.org\/webdev\/#\/schema\/person\/image\/bcf0b623715b0faf8c35c90d58d6acd6","url":"https:\/\/secure.gravatar.com\/avatar\/605bb18eedd69211a2a5783afe9a5ad6?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/605bb18eedd69211a2a5783afe9a5ad6?s=96&d=mm&r=g","caption":"Paul Craciunoiu"},"description":"I'm a full time web developer for Mozilla, with main focus on Django, Python, and JavaScript. I have a B.S.C.S. from UCSC. I\u2019ve been involved with Mozilla since 2008. If you're interested in more about me and what I do, check out my blog or follow me on twitter.","sameAs":["http:\/\/embrangler.com"],"url":"https:\/\/blog.mozilla.org\/webdev\/author\/paulc-2\/"}]}},"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/blog.mozilla.org\/webdev\/wp-json\/wp\/v2\/posts\/1479"}],"collection":[{"href":"https:\/\/blog.mozilla.org\/webdev\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mozilla.org\/webdev\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/webdev\/wp-json\/wp\/v2\/users\/211"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mozilla.org\/webdev\/wp-json\/wp\/v2\/comments?post=1479"}],"version-history":[{"count":0,"href":"https:\/\/blog.mozilla.org\/webdev\/wp-json\/wp\/v2\/posts\/1479\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.mozilla.org\/webdev\/wp-json\/wp\/v2\/media?parent=1479"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mozilla.org\/webdev\/wp-json\/wp\/v2\/categories?post=1479"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mozilla.org\/webdev\/wp-json\/wp\/v2\/tags?post=1479"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blog.mozilla.org\/webdev\/wp-json\/wp\/v2\/coauthors?post=1479"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}