1

I have som questions about structure in coding and I hope that this is the right place to ask these question/have this discussion. I am fairly new to python and have understood that in order to have a good structure you should (among other things) separate calculations and user interaction, for example you should have a separate print function.

I have tried to think about this when I refined my code, so I created a function print_and_save_stats that both saves statistics from my program and presents these, is this a good way to handle this or should I have a separate function for saving stats and one for printing stats? For example save_statsand print_stats?

def print_and_save_stats(games, h, k):
    
    player1wins=0
    player2wins=0
    ties=0 
    
    for game in range(games):
        result=scenario(h, k)
        if result==-1: ties+=1
        elif result==1: player1wins+=1
        else: player2wins+=1
        
        print('Player 1 wins:',player1wins)
        print('Player 2 wins:',player2wins)
        print('Tie:',ties)
 
    # Fake dataset
    height = [player1wins, player2wins, ties]
    bars = ('Player 1', 'Player 2', 'Tie')
    y_pos = np.arange(len(bars))
     
    # Create bars and choose color
    plt.bar(y_pos, height, color = (0.5,0.1,0.5,0.6))
     
    # Add title and axis names
    plt.title('My title')
    plt.xlabel('')
    plt.ylabel('')
     
    # Limits for the Y axis
    plt.ylim(0,games)
     
    # Create names
    plt.xticks(y_pos, bars)
     
    # Show graphic
    plt.show()

Gladly accepts all tips as I try to develop my knowledge in python. Edit I have now created to separate functions but however the values in save_stats doesn't work in print_stats and I can't see why. When I try to print for example player1wins in save_stats the correct information shows so it should not be empty. The error I get is TypeError: cannot unpack non-iterable NoneType object

def save_stats(games, h, k):
    
    player1wins=0
    player2wins=0
    ties=0 
    
    for game in range(games):
        result=scenario(h, k)
        if result==-1: ties+=1
        elif result==1: player1wins+=1
        else: player2wins+=1

    return [player1wins, player2wins, ties] # for returning
                    
def print_stats(games, h, k):
    
    if k ==3 or k == 5 or k == 7:
        if h == 1 or h == 2:
            
                player1wins, player2wins, ties = save_stats(games, h, k)
             
                # Fake dataset
                height = [player1wins, player2wins, ties]
                bars = ('Player 1', 'Player 2', 'Tie')
                y_pos = np.arange(len(bars))
                 
                # Create bars and choose color
                plt.bar(y_pos, height, color = (0.5,0.1,0.5,0.6))
                 
                # Limits for the Y axis
                plt.ylim(0,games)
                 
                # Create names
                plt.xticks(y_pos, bars)
                 
                # Show graphic
                plt.show()
        
                print('Player 1 wins:',player1wins)
                print('Player 2 wins:',player2wins)
                print('Tie:',ties)
        else:
            print('Playing surface does not exist, try again')
ida
  • 61
  • 5

1 Answers1

1

In a way, you have the answer already. The name of your function indicates already that it is doing two different things. On the one hand it analyzes the game results and derives the stats and on the other hand it prints the results. Separating code doing different actions usually supports readability for you and others.

Edit What you are missing here, is that your variables in save_stats are scoped (further reading).

You could experiment a little with a minimal example

def first_scope():
    x=1
 
def second_scope():
    x = first_scope() 
    print(x)
    # Be aware that using another variable name than "x" in second_scope will produce the same result

second_scope()

This example will print None. But we want 1. To achieve that, you need to get the value of x out of first_scope by returning its value (further reading).

There are also some further improvements you can do to your code, e.g.:

juergen_p
  • 58
  • 5
  • Thank you @juergen_p I have now updated with two new functions instead of one. You can see this in my question if you would like. – ida Jan 08 '21 at 15:26
  • I‘ve posted also a new edit of my answer. – juergen_p Jan 08 '21 at 18:11
  • Thank you @juergen_p, I really appreciate your answer! While returning player1wins, player2wins and ties I unfortunately get ``TypeError: cannot unpack non-iterable int object``instead. However on your smaller example I manage to get it right so I now understand my problem better! I will also definitely look into your suggestions about further improvement and read all your links. Thank you again for your time and effort! – ida Jan 08 '21 at 21:50
  • I find out that ``return [player1wins, player2wins, ties]``worked for returning all three in ``save_stats``, I edited they into the code if anyone would like to see what was missing and how they should/could be written. – ida Jan 08 '21 at 22:08