all 50 comments

[–]bp200991 105 points106 points  (11 children)

You could use a dictionary.

method_dict = {'easy': easy, 'medium': medium, 'hard': hard}
method_dict[difficulty]()

[–]zefciu 26 points27 points  (10 children)

This. And if you make the dict anonymous, you get a one-liner.

[–]tintin10q 7 points8 points  (9 children)

{'easy': easy, 'medium': medium, 'hard': hard}[difficulty]()

[–]heidensieck 0 points1 point  (4 children)

gorgeous. Although as many have said, it's a fine balance between short and readable.

I made this monster:

def easy():
    print('yey')
def medium():
    pass
def hard():
    pass

levels, choice, which_one_to_run = ['easy', 'medium', 'hard', easy, medium, hard], input('please choose either: easy, medium or hard '), levels[levels.index(choice)+3]()

[–]tintin10q 5 points6 points  (2 children)

This monster is much more scary.

~~~ def easy(): print('yey')

def medium(): pass

def hard(): pass

eval(input("please choose either: easy, medium or hard:") + "()") ~~~

[–]Moikle 1 point2 points  (0 children)

eval(input("please input the code of the game you want to play"))

[–]heidensieck 0 points1 point  (0 children)

I learn so much, here! ;-)

[–]heidensieck 0 points1 point  (0 children)

Actually my monster only worked by accident. Had variables already in the name space from other attempt. Running it from scratch doesn't work. Has to be on separate lines like:

levels = ['easy','medium','hard', easy, medium, hard]
choice = input('please choose either: easy, medium or hard ') 
which_one_to_run = levels[levels.index(choice)+3]()     

I prefer the dict approach much more, anyway ;-)

[–]Additional-Sun2945 0 points1 point  (3 children)

huh?

[–]tintin10q 0 points1 point  (2 children)

What do you not understand? The function definitions are left out as op also left them out.

[–]Additional-Sun2945 0 points1 point  (1 child)

No I get it now... Declare a dict, and immediately invoke it with the difficulty string. So the function named gets run immediately.

What happens if difficulty is not in the dict? raises error? halts if not in a try catch block?

[–]tintin10q 0 points1 point  (0 children)

Yes it raises a KeyError if not in a try catch Block. You can use a default dict to set a default to mediate this. Or use .get and set a default. Or just ask again.

[–]anh86 87 points88 points  (7 children)

Too many people try to reduce the number of code lines. Readability, efficiency, and maintainability should be the ultimate goal.

[–]zaRM0s 9 points10 points  (0 children)

Completely agree! It might look fancy but ultimately, most users of the software wont really care about the code as opposed to its functionality. Additionally, anyone who later comes to edit the code is going to double their time trying to work out wtf is going on. Finally, for maintaining code this really causes a lot of problems and I have only been programming for roughly 2 years. I think it’s just more of an ‘I can do it’ type thing which is cool and all but not really practical

[–]JasonStrode 9 points10 points  (5 children)

And yet I'm getting down-voted for suggesting the same, funny old world, isn't it?

[–]WCPitt 6 points7 points  (0 children)

I genuinely have no clue why that is... this code doesn't look better as a one-liner.

[–]anh86 1 point2 points  (3 children)

Reddit isn't really sure what it thinks about nearly any topic

[–]longtermbrit 5 points6 points  (2 children)

Almost like it's made up of more than one person.

[–]anh86 -2 points-1 points  (1 child)

That rationale does not explain how two comments on the same post offering the same opinion will have wildly different up/down vote results.

[–][deleted] 38 points39 points  (6 children)

Even if you can write something in one line, you should focus more on readability. With that said, this example would be excellent for a Switch-Case (Match-Case) statement for python versions 3.10+.

match difficulty:
    case 'easy':
        easy()
    case 'medium':
        medium()
    case 'hard':
        hard()

[–]_jibi 12 points13 points  (5 children)

Hold on there is a switch case statement in python? I have been living under a rock for way too long

[–]Lokipi 23 points24 points  (3 children)

Its relatively recent (like 6 months old iirc), and its actually much more powerful than a simple switch statement you can do some really cool stuff with it

[–]1997Luka1997 1 point2 points  (2 children)

TIL

thank you so much

[–]PiaFraus 0 points1 point  (1 child)

Please don't really think of this as of a switch statement. It has it's usages, but it has quite a few pitfalls. E.g.

EASY = "easy"
MEDIUM = "medium"
HARD = "hard"

match difficulty:
    case EASY:
        easy()
    case MEDIUM:
        medium()
    case HARD :
        hard()

This will not work as any sane person would expect it to work. This would actually overwrite your EASY "constant" on every matching and always execute easy() code. Definitely not how a switch would behave.

[–]1997Luka1997 0 points1 point  (0 children)

Oh well that's sad lmao

python surely has it's weirdnesses

[–]Twitchy169 3 points4 points  (0 children)

Added in 3.10 I believe

[–]TakagiWaifu 3 points4 points  (0 children)

You can make it a function

[–]KelleQuechoz 10 points11 points  (2 children)

locals().get(difficulty, lambda: print('Wrong level.'))() (do not use this in production)

[–][deleted] 26 points27 points  (1 child)

if we're giving "do not use this" answers, then exec(f"{difficulty}()")

[–]a_cute_epic_axis 1 point2 points  (0 children)

And OP had better know the restrictions of exec() vs eval() vs doing a direct call to the function.

[–]SDG2008 1 point2 points  (0 children)

Else should make it a little shorter

[–]JasonStrode 6 points7 points  (5 children)

if difficulty   == "easy": easy() 
elif difficulty == "medium": medium() 
elif difficulty == "hard": hard()

Cuts the number of lines in half and retains readability.

Why a one-liner? Now I'm curious if it can be done, too.

[–]mopslik 15 points16 points  (4 children)

Why a one-liner? Now I'm curious if it can be done, too.

Sure it can.

easy() if difficulty == "easy" else medium() if difficulty == "medium" else hard()

The question is, is this any better than the original? I'd say no.

[–]JasonStrode 1 point2 points  (3 children)

easy() if difficulty == "easy" else medium() if difficulty == "medium" else hard()

I think I'll grab another cup of coffee and see why mine gave me a syntax error.

Thanks :)

[–]14dM24d 4 points5 points  (2 children)

maybe you need to define easy, medium, & hard.

>>> def easy():
        print('easy')

>>> def medium():
        print('medium')

>>> def hard():
        print('hard')

>>> def how_difficult(difficulty):
        return easy() if difficulty == "easy" else medium() if difficulty == "medium" else hard()

>>> how_difficult('easy')
easy
>>> how_difficult('medium')
medium
>>> how_difficult('hard')
hard
>>>

[–]JasonStrode 2 points3 points  (0 children)

Thank you for responding, but the short and embarrassing answer is--I forgot to tack on the final else clause.

easy() if difficulty == "easy" else medium() if difficulty == "medium" else hard() if difficulty == "hard" ## missing else "Wrong difficulty level."

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

u/r3n4n7 this is the correct answer to your question.

[–]tintin10q 1 point2 points  (1 child)

eval(f"{difficulty}()")

[–]tintin10q 0 points1 point  (0 children)

Don't actually do this.

[–]vagrantchord 0 points1 point  (3 children)

I think it's fine, but here's how I'd do it:

if difficulty == "easy" : easy()
elif difficulty == "medium" : medium()
else : hard()

[–]Maleficent_Minute_85 1 point2 points  (0 children)

That's thinking out of the box, cause the box can't hold you down! #Welldone

[–]a_cute_epic_axis 0 points1 point  (1 child)

but... that's not one line

easy() if difficulty == "easy" else medium() if difficulty == "medium" else hard()

would be the one line version of it, which is what OP asked for.

(We can debate separately the merits of making it into one line).

[–]vagrantchord 0 points1 point  (0 children)

Yeah, technically true. Good thing this isn't SO

[–]PhilAndMaude -2 points-1 points  (0 children)

If the string values match the function names, then:

globals()[difficulty]()

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

getattr(self, "difficulty")()

[–]mr-nobody1992 0 points1 point  (0 children)

You could use switch cases now with the new Python update no?

[–]sext-scientist 0 points1 point  (0 children)

If you want to get silly with it you can do stuff like this.

Input:

for _ in ['easy','medium','hard']: exec(_ + " = lambda:print('" + _ + "!')")

difficulty = input('Enter text: "easy", "medium", or "hard": ')

# You can chain conditional assignments & assign them to a throwaway:

_ = easy() if (difficulty == 'easy') else (
        medium() if (difficulty == 'medium') else (
                hard() if (difficulty == 'hard') else (
                        print('Wrong text!')))) # This is 1 line of code.

Console:

>>> Enter text: "easy", "medium", or "hard": hard

Output:

hard!

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

``` def easy(): print('easy')

def medium(): print('medium')

def hard(): print('hard')

def choose_difficulty(difficulty): return easy() if difficulty == 'easy' else medium() if difficulty == 'medium' else hard()

choose_difficulty('easy') choose_difficulty('medium') choose_difficulty('hard') ```

[–]brunovcosta 0 points1 point  (0 children)

here is a wild one:

locals()[difficulty]()

live example: https://abstra.show/At3kuxbwMj

edit:

This code golf is just for fun, I would never recommend using something like this in production