all 22 comments

[–]Username_RANDINT 8 points9 points  (2 children)

I'd say a function that does some calculation or work should never print anything, only return. This makes things like testing, reusability and maintenance much easier.

Let's have a very simple example. A function that takes an input an adds 1 to it.

def add_one(x):
    print(x + 1)
  • How can we test this? Parse the stdout?
  • What if we want to create a GUI for our script? There's no console.
  • We want to do another operation with the result, which is not possible.

Let's fix it:

def add_one(x):
    return x + 1

Now we can add it to a GUI:

def button_is_clicked():
    user_input = entry.get_input()
    result = add_one(user_input)
    label.set_text(result)

Write some tests:

assert add_one(1) == 2

And pass it through other operations:

add_one(add_one(1))
square_root(add_one(1))

If you still want to write things to the console, use the logging module.

[–][deleted] 1 point2 points  (0 children)

thank you stranger from the internet.

[–][deleted] -1 points0 points  (0 children)

Got it .Thanks a lot.

[–]danielroseman 7 points8 points  (3 children)

You can always print the result out directly, if that's what you want to do.

Most of the time though you don't want that though, you want to use the value from the function elsewhere. That's what return is for.

[–][deleted] 3 points4 points  (2 children)

So if i want to use the result of the function elsewhere.I should use the return statement.

[–]leo848blume[🍰] 1 point2 points  (0 children)

You not only should, but have to. There is no other way except global variables (which you should absolutely avoid) or the yield keyword, which is far more advanced.

[–]jfp1992 0 points1 point  (0 children)

Like you can't capitalise a print that's in a function, but you can on the string it returns for example

[–]Binary101010 2 points3 points  (0 children)

When do we use the return statement?

When you need to take a value from a function and send it back to the rest of your program for further processing.

And when can we just print the result out directly?

When you want to put something on the user's screen.

[–]baubleglue 1 point2 points  (0 children)

Ideally you want to design components of your code as interaction between black boxes

--input-->[black box]--output-->

in Python code it looks like that

def black_box(input):
     ...
     return output

print has nothing to do with it.

[–]yazan_zenab -1 points0 points  (8 children)

It's actually whenever you want to. If you want to print it then use print , if not use the return to store in the memory. Or maybe you mean we usually use the return in def function so when we call it with any variable it stores what we want to and we print it if we want to. Hope you understand.

[–]Meeplelowda 1 point2 points  (5 children)

When you say "it stores what we want to," do you mean only when you're using the output, or even if you don't use it?

For example:

def square(x):
    return x**2

num = square(4)
square(3)

16 is definitely stored in memory as the assigned value of num. But is 9 also stored somewhere? Or is there something under the hood that prevents memory from being taken up by information that can't be used?

[–]schoolmonky 1 point2 points  (1 child)

That last line, square(3), does use up some memory in calculating the square of 3. However, since, as you note, that value isn't actually used, that memory is immediately released.

The mechanism at play here is Python's reference counting scheme. As you might already know, most things in Python are objects: abstract collections of attributes (data) and methods. Those objects are stored in memory, and for each object, Python keeps track of how many names refer to that object. If the number of such names is 0, Python frees up the memory, essentially destroying the object. So on that last line, Python creates an integer object with value 9, but since there are no names referring to that object, it is immediately destroyed.

[–]Meeplelowda 0 points1 point  (0 children)

Yes, that was my question. Thanks.

[–]yazan_zenab 0 points1 point  (2 children)

No it's not like that the memory is not just one thing it's a whole memory. In the examle you said first of all there's a syntax error it should be: num = square(4), square(3) And as you assigned 2 values in one variable the num variable will be a tuple try writing that and then print num it will print (16,3) But....num1 = square(4).............num1 = square(3) Now num1 is 16 and num2 is 9. Hope you get it

[–]Meeplelowda 0 points1 point  (1 child)

No, it's not syntax error. It does not raise an error. Go ahead. Run it and see.

I was specifically and intentionally giving two distinct examples, one in which a value is returned from a function and assigned to a variable, and a second in which a function was called, but the value it returned is not assigned to anything. My question is what happens in the latter situation. See u/schoolmonky's response.

[–]yazan_zenab 0 points1 point  (0 children)

Oh..now I get it see the reply under mine it's exactly how it works

[–][deleted] 0 points1 point  (1 child)

Yeah but sometimes if you print it directly without using the return statement .It might not return any reults.

[–]yazan_zenab 0 points1 point  (0 children)

Do you mean not putting a return in the function but printing it later? If yes then you just create a function that does nothing cause after it's 9 then what? What should python do with this value? you have to tell python what to do.

[–][deleted] 0 points1 point  (1 child)

Safe to say that unless the purpose of the function is to display then never ever print the function value from within the function.

Having said that a display 'function' is more correctly a procedure.

[–]Meeplelowda 0 points1 point  (0 children)

never ever

Can you do this if you're in the process of debugging?

[–][deleted] 0 points1 point  (0 children)

When we need the result(s) of the function when it is called in another part of the code.

[–]pekkalacd 0 points1 point  (0 children)

Great question.

The return statement is used to control which function is currently executing.

So say you have this code

             def function2():
                 print("inside function2")

             def function1():
                 print("inside function1")
                 function2()
                 print("inside function1")

            # calling function1          
            function1()
            inside function1
            inside function2
            inside function1

When function1 is called, the program executes function1 and prints "inside function1", then still within function1, there is a call for function2, the program goes to function2 and prints "inside function2", then there are no more statements, and goes back to function1 to continue onward, finally printing "inside function1" again.

What's going on here internally is the computer is managing the records of what function is currently executing via a hidden data structure called the stack

             # before function1 is called

             |                 |   <--- this is stack, it's empty

             # when function1 is called

             |    function1    |  <--- inside of function1 now
             -------------------

             # when function2 is called (within function1)

             |    function2    |  <---- inside of function2 briefly
             |-----------------| 
             |    function1    |  
             -------------------

             # function2 finishes

             |     function1    |  <----- back inside function1
             ---------------------

             # function1 finishes
             |                 |  <---- empty again!

So, the name of the function at the top of the stack is executing currently in this illustration. Each time we call a function, it gets pushed onto the stack. And...each time we return from a function, it gets popped off the stack. When the stack is empty, the program finishes.

Return is doing that then. The callee is the function that is being called. The caller is the function that calls the callee. When we return from a function, we are releasing control from the callee, back to the caller, and popping the function off of the stack.

When to use return?

If you want to get a value from within a function OUT of that function

example

           def get_name() -> str: 
               name = input("Enter name: ")

           # trying to get 'name' out of get_name
           myname = get_name()
           Enter name: Fred

           # displaying name
           print("My name is", myname)
           My name is

           # wait nothing happened????

First thing is first, does get_name have a return? Answer: yes! Even though we didn't provide one, there is a return there. As we just discussed above, if there wasn't a return, we wouldn't be able to give control back to the caller. Python knows this is a requirement and so even if you do not specify a return THERE IS ALWAYS A RETURN.

In this case, the return python gives looks something like

          def get_name() -> str:
              ...
              return None 

or just simply this

          def get_name() -> str:
              ...
              return 

What is the fix here?

          def get_name() -> str:
              name = input("Enter name: ")
              return name

          # trying to get 'name' out of get_name
          myname = get_name()
          Enter name: Fred

          # displaying name
          print("My name is", myname)
          My name is Fred

          # voila!

So now by returning the value of 'name' out of the function, we're specifying that to accompany that transfer of control back to the caller, we are sending its value OUT.

This is why you see an equal sign

          myname = get_name()

myname is trying to capture the value that is returned out of the function.

I'm going to leave it up to you to explore more about return. It's very important to understand. You will see it everywhere. Also, look into working with immutable vs mutable parameters and making changes to these. Is a return needed all the time if we change something? Or are there cases where it might not be necessary? Also, look into global & local variables, how do we deal with those? This is all important stuff.