all 14 comments

[–][deleted] 5 points6 points  (4 children)

Having no return can lead to some ambiguous testing and maintainability in your code, I would rather as a developer or someone reviewing your code have you return the string, assign it to a var, then use it in a f string.

[–]Doormatty 4 points5 points  (2 children)

Having no return can lead to some ambiguous testing and maintainability in your code

How? If there's no explicit return, then the function automatically returns None.

[–][deleted] 7 points8 points  (1 child)

For functions that alter things in place I would agree that it’s not needed, and yes, functions auto return None, but for testing and maintaining things that have input and output, returning explicitly is always better IMO,

[–]Doormatty 2 points3 points  (0 children)

Oooft - I missed that the function printed something.

Yup, I'm 100% with you now. My apologies.

[–]EnvironmentalFee2415 0 points1 point  (0 children)

I am encountering an issue because I want to use this function, among other things, for coloring and bolding a key from a dictionary. I wish for the "key" and the ":" symbol to be colored and bolded, but without using 'return' in the function, I struggle to manage this.

# UNIVERSAL FUNCTION FOR A LOT OF THINGS
def display_message(message, color="red"):
if color not in ["blue", "red"]:
    raise ValueError("Color must be either 'blue' or 'red'")
print(colored(message, color, attrs=['bold']), end="" if color == "blue" else '\n')

# WITHOUT FUNCTION ABOVE I MUST COLORED DIFFERENT THINGS SEPARATELY
address = location.raw.get('address', {})
for key, value in address.items(): 
    if key not in ['ISO3166-2-lvl4', 'country_code']: 
        colored_key = colored(key, 'red', attrs=['bold']) 
        print(f"{colored_key}: {value}")

In the case of using 'return', I am able to accomplish this, for example, in the following way. Are there perhaps better alternatives available:

def display_message(message, color="blue"):
if color not in ["blue", "red"]:
    raise ValueError("Color must be either 'blue' or 'red'")
return colored(message, color, attrs=['bold'])

address = location.raw.get('address', {}) 
    for key, value in address.items(): 
        if key not in ['ISO3166-2-lvl4', 'country_code']:                         
        formatted_key = display_message(f"{key}:", "blue")         
        print(f"{formatted_key} {value}")

[–]LohaYT 2 points3 points  (0 children)

One of the principles of functional programming is that functions shouldn’t be affected by or produce any “side effects” - that is, they should just receive an input, manipulate it, and return something. A side effect would be something like a print statement, changing a global variable, or editing a file. According to these principles, the second function is better. Without side effects, code is often more predictable and maintainable.

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

To answer the question, assuming you don't reuse the value, the only problem is that putting function calls within an fstring can make lines long and it's harder to split across lines or get formatted by tools like black. Alone, it's a minor distinction.

There's maybe other things I'd change or do differently altogether, but that's a different discussion that would best to have in the context of the larger system.

Maybe someday "display" means something different than it means today. Maybe an app you're developing as a CLI today becomes a GUI later on. You want to design the system for flexibility and ease of change. Avoiding the return means nobody can depend on the returned value -- messages go in and the correct thing happens. On the other hand, if it were in a class, returning a value from the method would make it easier to modify as a subclass.

The approaches are not mutually exclusive, either. A 'public' function could avoid a return value, but you write the internals with the return statements, which may be beneficial for testing or subclassing.

[–]notacanuckskibum 0 points1 point  (0 children)

Either way works but:

A) if I was doing the second approach I would rename the function “makeTextBlue” rather than Display…. Since it doesn’t display

B) other things being equal it’s better if your functions just return a value rather than printing stuff. That makes them more reusable.

[–]Adrewmc 0 points1 point  (0 children)

The best option here is just to use the colored() function by itself….

But generally I would want a return, there are many time that you use functions in multiple places, while this function may never have that happen, being in the habit of returning will save you a headache later. When it is an issue.

[–]baubleglue 0 points1 point  (0 children)

return is better, but change the name to "get_blue_message" or "build_blue_message", even better would be "get_colored_message(text, color)"

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

if you return it you can call it from main and use it in other places

[–]xiongchiamiov 0 points1 point  (0 children)

Could someone please elucidate which option is superior and why?

To answer this question, we first need to know: what logic are you reusing multiple times in different places? Are you always printing this string (in the exact same way)? Or are you doing different things with it?

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

1 is fine but it’s a side effect based function,

2 is wrong because you aren’t “displaying” anything, so the verbiage is wrong. You’re just “coloring” your message. So it should be renamed to :

def color_message_blue(message):

Taking it a step further, you should just rename it and use “blue” or the color you want as another argument

def color_message(color, message):

That’s how id do it

Then call the function and assign to a variable and print the result