For the following code, it seems to me that we are assigning the print function to the variable, spam.
spam = print('Hello!')
I'm wondering why doesn't calling spam, print out "Hello!"?
Because spam isn't a function, it's the result of calling the function print with the argument 'Hello!', which is None, of type NoneType.
If you want to assign that expression to a variable, then you can use a lambda:
l = lambda: print('Hello!') # Doesn't actually call print
l() # 1. Prints 'Hello!'
l() # 2. Prints 'Hello!'
l() # 3. Prints 'Hello!'
spam = print('Hello!')
evaluates the expression on the right hand side and binds its value to spam. The return value of the (Python 3) print() function is None, so spam refers to None:
>>> spam = print('Hello!')
Hello!
>>> spam is None
True
One way to handle this is to create a partial function with functools.partial():
>>> from functools import partial
>>> spam = partial(print, 'Hello!')
>>> spam
functools.partial(<built-in function print>, 'Hello!')
>>> spam()
Hello!
Or a lambda expression:
>>> spam = lambda : print('Hello!')
>>> spam
<function <lambda> at 0x7f619cabf9d8>
>>> spam()
Hello!
Essentially both of the above use a closure around a function like this:
def printer(s):
def f():
print(s)
return f
>>> spam = printer('Hello!')
>>> spam
<function printer.<locals>.f at 0x7f619cabfb70>
>>> spam()
Hello!
>>> spam = print('Hello!') Hello! For this, what is hello referred as? You mentioned that it is not the return value. Thank you!Hello! is there because that's what print() does - it prints a string to the terminal. That's why you see Hello! displayed, however, the actual return value of the print() function is None as shown by spam is None.A function, depending on how that function is written, may or may not have an explicit return value. It's up to the author of the function to decide how he wants to implement his function. A function with an explicit return value must have a return statement in it. The return statement causes the function to end and for the value following the return statement to be "returned" to the calling code. When a function reaches the end of its code without an actual return statement, it's like there's an implicit return None at the end. So...
def is_5(num):
if num is 5:
return True
What happens above? If num is 5, the function returns the boolean value of True. But if num is not 5, there is no final return statement, so the implicit None is returned.
As to your question, there is also a difference between the "name" of a function and invoking the function. In our example above, the "name" of the function is is_5, and we invoke it by following the name of the function with parentheses. If there are no parentheses following the function name, then the function name is just like any other variable, only it happens to hold a reference to a function. When you follow it with parentheses, that causes the function to be invoked. This is why we can call
is_5(2+3)
but we can also say:
myfunc = is_5
myfunc(2+3)
and get the same exact result. As for lambda and functools.partial, both are used to create what are known as "nameless" functions -- they return a reference to a function, but that function has no name. You can capture the return from either of those and store it in a variable. Then, you can invoke the function by following the name of the variable with parentheses, just like above. Keep in mind that the function does not get run till it's invoked using parentheses. So, for example:
mylambda = lambda x: True if x is 5 else None
mylambda(1+4)
Having said all this, regarding your question, the variable spam gets whatever the return value, if any, of the print() function returns. print() has no return value, so spam gets assigned the value None. If you wanted to assign a reference to the print function to spam, you could say:
spam = print
And then later you could say
spam("Hello!")
and you would get your "Hello!" string printed to the screen at that time.
Also, having a return value and printing strings to the screen or terminal are two different things. A function could do both or neither of those things and still be a useful function. It all depends on what the coder was trying to accomplish.
print, instead of teaching newbies to be comfortable with playing with their code in a debuggerprintfunction. Just likesomelist.append(x)has a side effect of mutating the list object, the print functions puts some bytes in the standard output buffer. Note,.appendalso returnsNone. Most functions that are used for a side effect returnNonein Python. One counter example would besomelist.pop()which mutes the list (a side effect) and it also returns the popped value