You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

438 lines
12 KiB

<!--
title: Variable Scope
type: lesson
duration: "00:30"
creator: Brandi Butler
-->
## ![](https://s3.amazonaws.com/python-ga/images/GA_Cog_Medium_White_RGB.png) {.separator}
<h1>Unit 3 Lab: Variable Scope</h1>
<!--
## Overview
This lesson introduces local and global scope with a few examples. If there is time, give students examples of broken programs that mix up global and local scopes, and ask them to fix it.
## Learning Objectives
In this lesson, students will:
* Define variable scope.
* Use the global keyword to access global variables.
* Explain the order of scope precedence that Python follows when resolving variable names.
## Duration
20 minutes
## Suggested Agenda
| Time | Activity |
| --- | --- |
| 0:00 - 0:03 | Welcome |
| 0:03 - 0:08 | Local Scope |
| 0:08 - 0:18 | Global scope |
| 0:18 - 0:20 | Summary |
## Differentiation and Extensions
- There are no exercises involving classes, built-in scope, or enclosed scope. If there is time and your students seem confident, create some — or challenge your students to come up with examples themselves.
## In Class: Materials
- Projector
- Internet connection
- Python 3
-->
---
## Lesson Objectives
*After this lesson, you will be able to…*
* Define variable scope.
* Use the global keyword to access global variables.
* Explain the order of scope precedence that Python follows when resolving variable names.
<aside class="notes">
**Teaching Tips:**
- Jot these on the board for reference.
</aside>
---
## 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!
<aside class="notes">
**Teaching Tip:**
- Don't mention programming here. Just make sure the class is clear on the idea of scope and how, if we aren't specific, we'll look first in town, then state — continue getting wider.
</aside>
---
## 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!
```
<aside class="notes">
**Teaching Tips:**
- Walk through this carefully!
- Run it in an interpreter, repl.it, or file to show it working (remove the last `print` to stop the error).
- Terminology is next — just get students to understand the idea.
**Talking Points:**
- Any variable declared or assigned inside of a function is local to that function.
- This is the most specific level of scope and is, ideally, where most of your variables should be declared.
- Only the function in which the variable was declared has access to this scope — i.e., the variable is out of scope for everything but that function.
</aside>
---
## Global Scope
Variables that are in **global scope** can be accessed anywhere.
- Python will check for a local variable before using a global one.
```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.
```
<aside class="notes">
**Talking Points:**
- If some variables are specifically local, what are the variables outside of a function or class called?
- Any variable declared or assigned outside of any function or class is considered "global."
- Global variables are accessible from anywhere in the script. This is not necessarily a good thing, however, because those variables can be accessed, changed, or reassigned by anything, and this can lead to troublesome bugs.
- This is another case where Python has our backs. It's preventing us from making an accidental error that could easily occur in many other languages.
* Python assumes local unless otherwise specified.
* Meaning, these `x`s are three different variables.
* Python does this to prevent unexpected behavior and accidental bad practice.
* It's considered sloppy to have too many global variables.
* If you have a large code base, you may have forgotten that you used a variable name elsewhere.
* If you're working on a team, another person may have used a variable name without your knowledge.
</aside>
---
## 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
```
<aside class="notes">
**Talking Point:**
- Why would you want to have different variables with the same name? Do you expect each `x` and `y` in this code to perform independently?
</aside>
---
## We Do: Accessing Scopes
Let's start with global scope:
```python
foo = 5
print(foo)
foo = 7
print(foo)
```
<aside class="notes">
**Talking Point:**
- Python makes it a little trickier than other languages to fiddle around with global variables if we're not already in that scope. First, start up a blank script. The following line will assign a global variable named foo the value of `5`. We can easily reassign and access that variable with the following lines. That's the global scope: There's no restriction on accessing or mutating a variable.
**Teaching Tip:**
- Run all the code in these slides in an interpreter for students to see. Encourage them to do this with you.
</aside>
---
## 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!
<aside class="notes">
**Talking Points:**
- If you run this code, you will get an error: `NameError: name 'bar' is not defined.`.
- The variable bar is only accessible from inside the `coolFunc()` function.
- We called the `coolFunc()` function, but as soon as it finished running, the variable bar ceased to exist. Even while the function was running, it was only accessible to itself. But, `foo` in the global scope was still accessible.
</aside>
---
## 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
```
<aside class="notes">
**Teaching Tip:**
- Spend some time here. Ensure student understanding.
**Talking Points:**
- Hey! The variable `foo` went back to its old value after the function finished! Actually, not quite. Here's what happened:
- The line in the function where `foo` is assigned the value of `6` causes the creation of a new local variable.
- We then set this variable's value to `6`, the function prints the value, and the function finishes. However, the global variable `foo` was never touched by the function.
**Teaching Tips:**
- Run this!
</aside>
---
## I Do: The Global Keyword
You can call a global variable intentionally with `global`.
* What do you think happens if you forget the `global` keyword?
```python
foo = 5
def incrementFoo():
global foo
foo += 1
print(foo) # prints 5
incrementFoo()
print(foo) # prints 6!
```
<aside class="notes">
**Talking Points:**
- It is very clearly marked as `global`, so anyone using it is fully aware it's global.
- If you forget the `global` keyword, it simply becomes an unrelated local variable.
</aside>
---
## We Do: Global vs. Local
In the following code, there are three `print` statements. Before you run the code, guess what those `print` statements will print.
<iframe height="400px" width="100%" src="https://repl.it/@SuperTernary/python-programming-scope-quiz?lite=true" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe>
<aside class="notes">
**Repl.it Note:**
```
# Global variable x:
x = 1
# Only local x in this function:
def my_func1():
x = 2 # This is a different, local x
print(x) # Print the local x
# Using global x:
def my_func2():
global x # We declare we'd like to use the global x.
print(x) # Print that global x.
x = 3 # Change that global x.
my_func1()
my_func2()
# Print global variable x.
print(x) # Did x get permanently changed by my_func2()?
```
</aside>
---
## 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!`
```python
# Call functions in this order.
jump_in_river()
swing_vine_over_river()
jump_in_river()
```
**Pro tip:** Raise your hand if you need some help!
<aside class="notes">
**Teaching Tip:**
- Give students a few minutes. The answer is in a repl.it on the next slide.
</aside>
---
## We Do: Check Your Answers
* Did you remember the `global` keyword?
* What happens if that keyword is removed?
* Comment out line 4. What happens? Why?
<iframe height="400px" width="100%" src="https://repl.it/@SuperTernary/python-programming-scope-piranha?lite=true" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe>
---
## 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!
<aside class="notes">
**Teaching Tip:**
- Do a check for understanding.
</aside>
---
## 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/)