I'm pretty new to Python (I've been doing it for about 4 months, but not every day) and I've been struggling to get to grips with how to use functions and deploy them efficiently to solve problems.  To test my abilities, I created the below program to simulate the Monty Hall problem.  The program does the following things:It chooses a winning door at the start from list door = [1,2,3].It then asks the user to choose a door.Then it checks to see if the user's guess matches the winning door.If the user guesses the winning door, it randomly selects one of the two remaining doors to 'open'.  If, however, the user doesn't guess the winning door, it 'opens' the one remaining unpicked door.It then asks the user if they want to switch doors.  If the user picked the correct door first time out, then sticking with that choice wins the game and switching loses.  The reverse is true if the user didn't pick the correct door first time.Finally, it updates a running tally of wins and losses, then asks the user if he wants to play again.The program works and the probabilities are correct (I ran it 100 times just to make sure and got 74 wins and 26 losses, which is around about what I'd expect). I'm just not sure the program is as efficient as it could be.  In fact, given my relative lack of experience I'm pretty sure it isn't.  Would anyone be able to tell me how good they think the code is, how I could go about improving it?import randomwin = 0lose = 0while True:    door = [1,2,3]    x = 0    def pick_answer():        Computer chooses the winning door        answer = random.choice(door)        return answer    a = pick_answer()    def pick_guess():        User guesses winning door        guess = int(input(Please choose a door (1-3): ).strip())        return guess    b = pick_guess()    if a == b:        def montys_door_if_a_is_b():            If answer = guess, pick one of the remaining doors to open            global x            door = [1,2,3]            door.remove(a)            x = random.choice(door)            return x        c = montys_door_if_a_is_b()        print(You chose door {}.format(b))        print(I choose door {}.format(c))        def montys_final_choice():            Tells user which 2 doors are now left            door = [1,2,3]            door.remove(x)            door.remove(a)            y = door[0]            return y        d = montys_final_choice()        print(You're left with doors {} and {}.format(b,d))        choice = input(Will you SWITCH to door {}? y/n: .format(d))         def switch_or_stick():            Asks user if they want to switch. y = Lose / n = win            if choice == y:                print(Bad luck.  You lost.  You should have stuck as you already had the right answer.)                global lose                lose = lose + 1                print({} wins and {} losses.format(win,lose))            else:                print(Huzzah! You made the right choice by STICKING!)                global win                win = win + 1                print({} wins and {} losses.format(win,lose))        switch_or_stick()        input(\nPress Enter to play again)    else:        def montys_door_if_a_not_b():            If answer != guess, remove answer & guess and 'open' the remaining door            door = [1,2,3]            door.remove(a)            door.remove(b)            md = door[0]            return md        e = montys_door_if_a_not_b()        print(You chose door {}.format(b))        print(I choose door {}.format(e))        def montys_final_choice_if_a_not_b():            Asks user to choose between answer & guess            door = [1,2,3]            door.remove(e)        f = montys_final_choice_if_a_not_b()        print(You're left with doors {} and {}.format(a,b))        choice = input(Will you SWITCH to door {}? y/n: .format(a))         def switch_or_stick_redux():            Since answer != guess, if user sticks, he loses but if he switches he wins            if choice == y:                print(HUZZAH!  YOU WIN)                global win                win = win + 1                print({} wins and {} losses.format(win,lose))            else:                print(Bad luck.  You should have switched. You chose the wrong door at the start)                global lose                lose = lose + 1                print({} wins and {} losses.format(win,lose))        switch_or_stick_redux()        input(\nPress Enter to play again)
Monty Hall Simulator - Python
python;beginner;game;simulation
Functions should be used to cut down on code repetition so as to make code more concise and more readable. But you are constantly defining functions only to immediately invoke them once on the very next line. That makes the code less concise and less readable, and also forces you to introduce superfluous global variables. (It also seems like a JavaScript idiom -- are you coming from that language?) The code can be made more concise like this:import randomwin = 0lose = 0playing = Truewhile playing:    door = [1,2,3]    x = 0    a = random.choice(door) #Computer chooses the winning door    b = int(input(Please choose a door (1-3): )) #User guesses winning door -- .strip() is pointless    if a == b:        #If answer = guess, pick one of the remaining doors to open        door.remove(a)        x = random.choice(door)        c = x        print(You chose door {}.format(b))        print(I choose door {}.format(c))        #Tells user which 2 doors are now left:        door = [1,2,3]        door.remove(x)        door.remove(a)        d = door[0]        print(You're left with doors {} and {}.format(b,d))        choice = input(Will you SWITCH to door {}? y/n: .format(d))         #Ask user if they want to switch. y = Lose / n = win        if choice == y:            print(Bad luck.  You lost.  You should have stuck as you already had the right answer.)            lose += 1        else:            print(Huzzah! You made the right choice by STICKING!)            win += 1        print({} wins and {} losses.format(win,lose))    else:        #If answer != guess, remove answer & guess and 'open' the remaining door        door.remove(a)        door.remove(b)        e = door[0]        print(You chose door {}.format(b))        print(I choose door {}.format(e))        #Ask user to choose between answer & guess        print(You're left with doors {} and {}.format(a,b))        choice = input(Will you SWITCH to door {}? y/n: .format(a))         #Since answer != guess, if user sticks, he loses but if he switches he wins        if choice == y:            print(HUZZAH!  YOU WIN)            win +=1        else:            print(Bad luck.  You should have switched. You chose the wrong door at the start)            lose += 1        print({} wins and {} losses.format(win,lose))    ans = input(\nPress Enter to play again, 'q' to quit)    if len(ans) > 0: playing = FalseA few other points:1) int() strips its input -- so the .strip() there was pointless2) You are setting door = [1,2,3] more often than needed3) Things like win = win + 1 were replaced by win += 14) The line print({} wins and {} losses.format(win,lose)) was moved to after then if statement5) montys_final_choice_if_a_not_b had absolutely no effect and was simply removed6) I made it so that it you can break out of the infinite loop without closing the Python shell.There are still improvements that can be made. In particular, you should find a way so that the code for the dialogue to switch doors occurs only once rather than twice, but this should be enough to get you started.