简体   繁体   中英

Why does foo = function() run the function in Python?

I'm up to Exercise 41 in Learn Python the Hard Way, and I'm having a really hard time wrapping my brain around the fact that the entire thing hinges on a function running just because it's been assigned as a value to a variable. I wrote up a little script to confirm that this is how it works, and it does:

def pants():
    print "Put on some pants!"

def shorts():
    print "And don't forget your underwear!"

zap = pants()
thing = shorts()

With the results being:

Put on some pants!
And don't forget your underwear! 

So obviously this happens, but I can't understand why the language works that way -- what the logic is behind the language that makes this a valuable way of operating. I think it'd be helpful for me moving forward to understand why this is, rather than just "that's the way it works."

For clarity: I'm asking (I guess) why the function is running, when all I'm doing is assigning it as a value for something. The print statements are just there so I can see that the function is indeed running.

It's the fact that I'm not ever actually running

pants() shorts()

that is confusing me.

To create a tortured analogy, if me-baking-cookies-at-home were "cookies()", and I were to make cookies on Saturdays, I might eventually believe that

Saturday = cookies()

but just thinking "hey, Saturday is cookie day" is not the same as actually baking cookies ... so why does just saying

Saturday = cookies()

actually bake the cookies, rather than just setting up Saturday with the variable "cookies()" for some later use?

When you use the parentheses () the function gets called. If you want to assign the function to the variable to reuse it you should remove there parentheses.

Example:

def pants():
    print "Put on some pants!"

def shorts():
    print "And don't forget your underwear!"

zap = pants
thing = shorts

And then when you want to call those functions:

zap()
thing()

So obviously this happens, but I can't understand why the language works that way -- what the logic is behind the language that makes this a valuable way of operating. I think it'd be helpful for me moving forward to understand why this is, rather than just "that's the way it works."

The language needs some way to distinguish between the function and the act of calling the function. That is what the parentheses provide.

f = foo

Now f is bound to the function itself. The function foo could be executed by f() .

f = foo()

This calls the function foo and binds the return value to f .

Note that whether or not you bind the return value to a name is irrelevant. Simply writing

foo()

will also execute the function but the return value will simply be ignored.

Although it may seem like your functions don't return anything, they do in fact. Quoting the Python.org documentation :

The return statement returns with a value from a function. return without an expression argument returns None. Falling off the end of a function also returns None.

So your functions really look like this:

def pants():
    print "Put on some pants!"
    return None

def shorts():
    print "And don't forget your underwear!"
    return None

Your assignments assign to zap whatever pants returns (ie the value of pants() ), and to thing whatever shorts returns. In your case, both are None , but of course the functions must be run in order to figure this out(*). Afterall, it could be that pants returns 42 during leap years, and that shorts returns 'Foobar' whenever some random number generator "rolls" a 6.


(*) Digression: That the functions "must be run" should not be considered universally true. In a pure setting , and leaving aside the specifics of Python (of which I know very little), a compiler might realize that both functions are identically None , and cause no calls to be made when the program is run. But a function that prints something (or inspects whether the current year is a leap year, or rolls a die) won't be pure.

zap = pants() will bind the return value of the function to the variable, so of course the function is run if you bind it to a variable.

def foo():
    return 1

var = foo()
print var

will print 1 .

I hope this helps.

Edit: If you expect the value of the variable to be "put on some pants", you are indeed confusing print and return , as people pointed out in the comments.

When the interpreter sees a function name followed by () it knows that it's supposed to execute that function.

What you're doing there is saying "assign the result of these functions to these variables".

But since you are not returning any values from those functions, you're not seeing anything in the variables.

However because you have a print statement in there, you are seeing the interpreter execute those functions as it attempts to assign the variable to results of that function.

Your functions are called because of the parenthesis after the name:

zap = pants()

This calls the function pants and puts the result in zap. If you had done this instead:

zap = pants

then zap would now refer to the pants function itself.

And if you just wrote

pants()

then the pants function would also get called, but the result (which is None) would never have been put in a variable.

From your question what I think you want zap will have the value "Put on some pants!" and thing will have the value "And don't forget your underwear!" . If that is your problem let's discuss it. Otherwise you do not need to read further as I just discussed about all that.

Let's make it some fun. When you define a function, you are like creating a machine that does what you want it to do. Now let's think of a machine that when you give some food in it, it chops them and ... does nothing! I mean I made that machine to chop foods and nothing else! You won't get your chopped food back, but indeed it chopped your food as you made it for.

Now, as you want your chopped food back, you create another machine that takes your food, chops them and return them to you. Fruitful machine, isn't it? ;-)

They are all true for functions in programming or math (though I don't know any void function in math! :P). When you are creating the function, you have to tell it whether it just does some work or it does some work and return the result . The way to tell a function is the return statement. In your functions, you have just told to do something. And that is print "......" so does the functions. You call the with () at end and the does their work, they prints it. But as I said if you don't tell it to return a result, it won't. And because it is not returning any result, nothing will be assigned with the variable (don't confuse him with None ). When you wrote those lines (if in interpreter) or run the script, you will see those lines printed but your zap and thing has no values.

So how to fix it? Tell them to return the lines to the variables. To tell the functions do that, replace the print statements with return statements. And never mind to experiment what you know, to know about what you know about your knowledge is true :-)

Hope it helps :-)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM