3

I am reading the book Python Programming for the Absolute Beginner by Mike Dawson and I was struck by a question that I had regarding functions.

Observing the code below

def func_1():
    name = input('What is your name?')
def func_2():
    print(name)

func_2()

I know that I cannot call the variable name in function 2 as it is local to function 1.

However, why can I call a function inside another function and then find the value of the user's input as such below?

def func_1():
    name = input('What is your name?')
    return name
def func_2():
    user_input = func_1()
    print(user_input)

func_2()
Christian Dean
  • 22,138
  • 7
  • 54
  • 87
Dave Smith
  • 185
  • 1
  • 2
  • 9
  • 2
    What exactly are you confused about? The calling of the function, or the `return`ing of the value to the caller? – deceze Jul 14 '17 at 12:21
  • Because you `return` the value – Ludisposed Jul 14 '17 at 12:21
  • @deceze calling a function inside another function. – Dave Smith Jul 14 '17 at 12:21
  • `func_1` returns a value in the second example, you are storing the value returned in a variable called `user_input` then printing it. – mrhallak Jul 14 '17 at 12:22
  • Try removing `return name` – Rahul Jul 14 '17 at 12:22
  • I think the confusion is about understanding scoping, and why `func_1` can be called inside `func_2` but `name` can't be called within `func_2`. This is putting aside what the `return` is responsible for. – idjaw Jul 14 '17 at 12:22
  • I'm not sure if this is even related, but does [this](https://stackoverflow.com/questions/45042273/why-can-i-use-a-variable-in-a-function-before-it-is-defined-in-python) have anything to do with your question? Can you clarify what exactly is confusing you? – Christian Dean Jul 14 '17 at 12:22
  • You call a function (`input`) in another function (`func_1`) in your first example, too. – chepner Jul 14 '17 at 12:23
  • It's because `func_1()` is in the global space. If `func_1()` had been defined inside another scope (such as inside a class, another namespace or function) then you wouldn't be able to access it from `func_2()` – Peter Featherstone Jul 14 '17 at 12:23
  • 4
    Why all the downvotes? This seems like a clear question and a reasonable mis-understanding for a beginner – Chris_Rands Jul 14 '17 at 12:28
  • @Chris_Rands thank you very much I was very confused and didn't know what the book was referring to! Please upvote. – Dave Smith Jul 14 '17 at 12:33

2 Answers2

5

The important thing to consider here is the scope of the variable and/or function names you're using. Global scope means everything can see it, whether it's at the top level, inside a function, or even inside a method, which is inside a class.

Local scope means it's locked within the context of that block, and nothing outside of the block can see it. In your case, that block is a function.

(Note that this is a mild simplification and more complex rules exist around modules and includes, but this is a reasonable starter for 10...).

In your example above, the function has been defined at the global level, so its name, func_1 has global scope (you might also say that it is in the "global namespace". That means that anything can see it, including code inside other functions.

Conversely, the variable name has local scope, inside func_1, which means it is only visible inside func_1, and nowhere else.

When you return name, you're passing the value of name back to whatever called that function. That means that the user_input = func_1() receives the value that was returned and stores it in a new variable, called user_input.

The actual variable name is still only visible to func_1, but that value has been exposed to outside functions by returning it.

Edit: As requested by @Chris_Rands:

There is a function in Python that will give you a dictionary containing of all the global variables currently available in the program.

This is the globals() function. You can check something is at global scope by seeing if it is in this dictionary:

def func_1():
    name = input('What is your name?')
def func_2():
    print(name)

func_1_is_global = 'func_1' in globals()  # value is 'True'
name_is_global = 'name' in globals()      # value is 'False'

One additional edit for completeness: I state above that you're passing the value of name back. This is not strictly true as Python is pass-by-reference, but the waters get murky here and I didn't want to confuse the issue. More details here for the interested observer: How do I pass a variable by reference?

n00dle
  • 5,949
  • 2
  • 35
  • 48
  • It would be good to also mention that `func_1` *is* scoped to be called by `func_2` and why. A small blurb about global/local scope would help here. – idjaw Jul 14 '17 at 12:24
  • 1
    You read my mind, was just updating accordingly. I'll add a tad more about local vs. global too. – n00dle Jul 14 '17 at 12:25
  • 2
    I think it would also be good to clarify that you are returning the _value_ of `name` and not the variable `name` itself. The OP seems to be confused because he thinks that `name` somehow becomes accessible in `func_2` upon returning it from `func_1`. – Christian Dean Jul 14 '17 at 12:29
  • @ChristianDean I've changed the wording as requested. – n00dle Jul 14 '17 at 12:38
0

func_2 calls func1, which returns a value which you can print inside func_2. In your first example func_2 cannot see a local variable of function_1.

Killer Death
  • 459
  • 2
  • 10