## ![](https://s3.amazonaws.com/python-ga/images/GA_Cog_Medium_White_RGB.png) {.separator}

Unit 3 Lab: Variable Scope

--- ## Lesson Objectives *After this lesson, you will be able to…* * Define variable scope. * Explain the order of scope precedence that Python follows when resolving variable names. --- ## Discussion: Delivering a Letter What if someone wanted to send Brandi a letter? If you just had "For Brandi," the mail carrier would give the letter to the first Brandi they see! They'd look: - First in the class. Is there a "Brandi" here? They get the letter! - No? OK, look in the town. Is there a "Brandi" here? They get the letter! - No? OK, look in the state. Is there a "Brandi" here? They get the letter! --- ## Discussion: Your Address That's why **scope** matters. We might have to get more specific. To correctly deliver the letter, if the mail carrier only looked in the scope of: Your class: - You're probably the only Brandi. - "For Brandi" is fine. Your town: - There might be multiple Brandis in the town. - "For Brandi, on Main Street" is a bit more specific. In your state: - There are multiple Main Streets in New York! - "For Brandi, on Main Street in Brooklyn" is more specific. --- ## Discussion: What Is `x`? Python has **scope**, too. We can have many variables with the same name, and Python will look for the most specific one. In different scopes, you can reuse the same name. Each one is a *completely different* variable. Functions and classes create individual **local scopes**. A **local variable** doesn't exist outside its local function or class scope. ```python def my_func1(): x = 1 # This is a LOCAL variable. print(x) # 1 def my_func2(): x = 5 # This is a DIFFERENT local variable. print(x) #5 print(x) # x is OUT OF SCOPE - no x exists here! ``` --- ## Global Scope - Variables that are in **global scope** can be accessed by any function. - Python will adopt an 'inside-out' strategy when evaluating variable of the same name, giving precidence to a local variable before using a global one. - When we define a variable _inside_ a function, it's local by default. - When we defint a variable _outside_ a function, it's global by default. ```python x = 2 def my_func1(): x = 1 print(x) # 1 - Python checks local scopes first. def my_func2(): x = 5 print(x) # 5 - Python checks local scopes first. my_func1() my_func2() print(x) # 2 - Python found no local scope; prints global variable. ``` --- ## Multiple Variables, One Name Use case: `x` and `y` are frequently used to represent numbers. Scope is important so they don't interact! ```python def add(x, y): return x + y def subtract(x, y): return x - y def multiply(x, y): return x * y def divide(x, y): return x / y divide (8,2) # Returns 4 multiply(3,1) # Returns 3 ``` --- ## We Do: Accessing Scopes Let's start with global scope: ```python foo = 5 print(foo) foo = 7 print(foo) ``` --- ## We Do: Accessing Local Scope What if we add a variable in a local function scope and try to access it from the global scope? ```python foo = 5 # Delete your other code. # Add this function and print calls instead. def coolFunc(): bar = 8 coolFunc() print(foo) print(bar) ``` It fails! --- ## Scope Can Be Tricky What do you think happened here? ```python foo = 5 def incrementFoo(): foo = 6 print(foo) # prints 6 print(foo) # prints 5 incrementFoo() print(foo) # prints 5 ``` --- ## You Do: Just a Day in the Jungle Open a new local file, `piranhas.py`. * Declare a global variable `piranhas_hungry` and set it to `True`. * Write two functions, `swing_vine_over_river` and `jump_in_river`. * In `swing_vine_over_river`: * Print `Ahhh! Piranhas got me!`. * Change `piranhas_hungry` to `False`. * In `jump_in_river`: * If `piranhas_hungry` is `True`: * Print `I'm not going in there! There are hungry piranhas!`. * Otherwise: * Print `Piranhas are full! Swimming happily through the Amazon!` --- ## You Do: Just a Day in the Jungle * Try this first by _not_ passing `piranhas_hungry` as an argument to `swing_vine_over_river` and `jump_in_river`. Can you make it work? * If you can't make it work, _pass_ `piranhas_hungry` as an argument to the two functions. Does it work now? ```python # Call functions in this order. jump_in_river() swing_vine_over_river() jump_in_river() ``` Speak up if you need some help! --- ## We Do: Check Your Answers * Are you able to access the global variable `piranhas_hungry` if it is _not_ passed as an argument to your functions? * Why or why not? * What is the solution to this? --- ## Summary and Q&A Python checks **scope** to find the right variable. - Functions and classes create individual **local scopes**. * A `local` variable doesn't exist outside its local function or class scope. - Any variable declared or assigned outside of any function or class is considered "global." - Variables that are in **global scope** can be accessed anywhere. Python will check for a `local` variable before using a `global` one. There can be more levels. Python always works from the inside out — keep that in mind as your programs get more advanced! --- ## Additional Resources * [Global vs. Local Variables](https://www.python-course.eu/python3_global_vs_local_variables.php) * [Variables and Scope](http://python-textbok.readthedocs.io/en/1.0/Variables_and_Scope.html) * [Nested Functions — What Are They Good For?](https://realpython.com/inner-functions-what-are-they-good-for/)