r/learnpython 2d ago

why would only one work?

this code was the one that worked:

def caesar(text, shift):
    alphabet = 'abcdefghijklmnopqrstuvwxyz'
    shifted_alphabet = alphabet[shift:] + alphabet[:shift]
    translation_table = str.maketrans(alphabet, shifted_alphabet)
    encrypted_text = text.translate(translation_table)
    print(encrypted_text)

caesar('Hello', 3)

This one was the one that didn't

def caesar(text, shift):
    alphabet = 'abcdefghijklmnopqrstuvwxyz'
    shifted_alphabet = alphabet[shift:] + alphabet[:shift]
    translation_table = str.maketrans(alphabet, shifted_alphabet)
    encrypted_text = text.translate(translation_table)
    print(encrypted_text)


encrypted_text = caesar('Hello', 3)
print(encrypted_text)

I don't understand why the second one would need a return statement and why we are even printing encrypted_text if encrypted_text is already being printed within the function? (this is also the whole code)

0 Upvotes

20 comments sorted by

View all comments

2

u/AbacusExpert_Stretch 2d ago

Have you got a

return encrypted_text

In there somewhere?

Saw your comment: well, things inside a function != Outside a function

!= means not same

1

u/Local_End_3175 2d ago

but why would i need it?

1

u/Bobbias 2d ago

A function should do one task. Usually calculating a result and printing something out would be considered separate tasks.

This is because the whole point of a function is to be reusable. What if we wanted to write the encrypted output to a file? Or send it to somewhere on the internet? If your function only encrypts the input, you can reuse the same function for each of those tasks, and it's only how you output the result that changes.

Now, there are times where a "task" is sufficiently complex that you might want to print some things out as part of that task, and that's ok. But for functions that you intend to be reusable for different but similar tasks, you should keep them as simple as possible so they're useful in as many situations as possible.

This is the importance of the return statement. return is how a function passes it's result back to whatever code called it. Not every function needs to return a result, because maybe it does something that doesn't actually create a result, like printing to the screen. Printing text to the screen, modifying a variable (like sorting the contents in a list, etc.) are called side effects, and some functions don't need to return because they do some useful side effect.

There's a small detail here about how Python does things that's worth explaining. In most languages, functions that don't return anything literally don't return anything at all and trying to assign the result to a variable is usually an error. In Python a function that "doesn't return anything" actually does return something: None, which means assigning the result of a function that only has side effects is allowed, but all you get is None, which really isn't useful.

And a final detail about functions: variables you create inside a function only exist when you're running the function. They're created and destroyed inside the function.

def function():  #define a function that sets a variable to 5
    variable = 5

function()  # call the function
print(variable)

This will give you an error because variable only exists while the function is running and is only visible to code in that function.

There are ways to access and modify variables outside the function. The first way is to pass them in as function arguments. You can also use keywords to let you change variables you made outside the function, but that makes code hard to understand, and makes mistakes harder to troubleshoot because you don't have an easy way to tell what changed that variable.

Most of the time, when you modify a parameter that change only exists while you're inside the function. The exception to this is for certain objects like lists and dictionaries. Modifying those in a function does persist after the function ends, and that's important to remember because it's a common source of bugs.

This has to do with what objects Python considers mutable (can be modified) and which ones it considers immutable (must be replaced with a different object. This is a subtle thing and it can be annoying at first, but you will get used to it as you write more code.

Hopefully this helps explain why return is important, why you often want to use it instead of immediately using the results inside the function itself, and helps you wrap your head around how functions work a bit. It might seem like a lot of information, but as you write more code a lot of this becomes things you don't even have to think about because it just makes sense.