# Environments and Scope

When Python is running your program, it does so in an isolated way, such that your program is not allowed to mess with other programs that may be running on your machine. Python does this by giving each program its own environment, it's own universe to exist in.

### What is Scope?

Consider the following program:

```python
def f(x):
    a = 4
    return 2 * x
print(a)
```

Executing this throws an error:

```
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined
```

Wait, what? Didn't we define `a` right there?

This discrepancy is to do with how variables are "scoped" in Python. When a variable is defined in a function, it is accessible within that function, and any of its child functions, but not to any functions outside that or even the file outside the function, as seen above. In our given example, the scope of the variable `a` is limited to the function `f`.

### What are Frames?

Frames are how Python implements the idea of scopes. Frames are also what you've been playing around with in [PythonTutor](https://pythontutor.com/visualize.html#mode=edit), if you've had a chance to visit that website yet.&#x20;

Think of it this way: every time Python defines a function call, it makes the "frame" in which it was defining the function the parent. Every time a function is called, a new "frame" is opened, that has access to everything within itself, and within its parent, and within its grandparent, and so on.&#x20;

Consider the following example:

```python
a = 6
def f(x):
    b = a + x
    def g(y):
        return x + y + a
    return g

func = f(5)
func(3)
```

In this code-block, first we create the "global frame". This is the outermost layer, created by default when a program is run. In this global frame, we define the function `f`. So `f`'s parent is the global frame. When we make the function call `f(5)`, we open a new frame — a sub-universe. In this frame, we can still access our parent's variables, so `a` is still accessible.

We create `g` within `f`, which means that `g`'s parent is `f`. This is why, when `g` is called, we can access the value of the variable `x`, which was defined in `f`. Note how we can also access `a` in `g`, because `a` is defined in the parent of the parent's frame — the global frame.

I hope that this section gave you a little bit of insight into how Python scopes variables. If this section was confusing, don't worry! It introduces a lot of new concepts very quickly, and might take some time to fully grasp. For a slower introduction to this concept, go ahead and read the next chapter — which is all about the intricacies of Python frames.&#x20;


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://calnotes.gitbook.io/cs61a-guidebook/building-blocks/environments-and-scope.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
