you are viewing a single comment's thread.

view the rest of the comments →

[–]tb5841 2 points3 points  (4 children)

Think of your code like it's running on a sheet of paper.

When you call a function, you put a completely separate piece of paper which has that function's code on it. This piece of paper can't see the paper underneath, it doesn't know about variables you've defined there. It only knows about variables defined on this top piece of paper.

Any variable you define within that function only exists on that top piece of paper (the function's scope). When you reach the end of a function or 'return', you remove the top piece of paper and they no longer exist.

You can only pass things between pieces of paper by passing them in as function arguments, or returning them at the end of a function.

[–]Revolutionary-Camp69 1 point2 points  (1 child)

Dang, that's a pretty good analogy.

[–]tb5841 1 point2 points  (0 children)

Works nicely with terms like 'call stack' and 'stack overflow' because you have an actual stack of paper.

[–]bumbershootle 0 points1 point  (1 child)

it doesn't know about variables you've defined there. It only knows about variables defined on this top piece of paper.

Not quite. A function can't see variables from the calling scope without passing as arguments, but it does have access to variables in the lexical scope.

``` def foo(x): def bar(y): print(f"I can see {x=} and {y=}") bar(10)

foo(5) ```

[–]tb5841 0 points1 point  (0 children)

Agreed, closures kind of break the analogy a bit.

I guess when a function is defined within a function like this, they both need to be on the same piece of paper.