the_martian
the_martian

Reputation: 634

Need help passing data from one function to another

I'm trying to pass the data from the accumulator variable "points" in the pyramid function to the statistics function. The way I tried doing just passes the original value of "points," which is 0. Also I want statistics to receive that and run separately from the pyramid function. The way it is now, the process taking place inside statistics in printing from within the pyramid function. How can I send data from a variable from one function to another for later use when I need to call the other function? The idea is that when statistics is called, it will display several pieces of information about the player--spanning across several games that will be played--like total points and the number of incorrect questions--as well as some other stuff to be implemented later.

import random
from random import choice
from random import randint

def pyramid():
    for k in range (1,3):
        print('\nPractice Problem', k, 'of 2')
        min_pyramid_size = 3
        max_pyramid_size = 5
        total_chars = 0
        num_rows = random.randint(min_pyramid_size, max_pyramid_size)
        for i in range(num_rows):
            x = ''.join(str(random.choice('*%')) for j in range(2*i+1))
            print(' ' * (num_rows - i) + x)
            total_chars = total_chars + x.count('%')
        try:
            user_answer = int(input('Enter the number of % characters' + \
                                    'in the pyramid: '))
        except:
                user_answer = print()
        if user_answer == total_chars:
            print('You are correct!')
        else:
            print("Sorry that's not the correct answer")
    for k in range (1,11):
        print('\nProblem', k, 'of 10')
        points = 0
        min_pyramid_size = 3
        max_pyramid_size = 5
        total_chars = 0
        num_rows = random.randint(min_pyramid_size, max_pyramid_size)
        for i in range(num_rows):
            x = ''.join(str(random.choice('*%')) for j in range(2*i+1))
            print(' ' * (num_rows - i) + x)
            total_chars = total_chars + x.count('%')
        try:
            user_answer = int(input('Enter the number of % characters' + \
                                    'in the pyramid: '))
        except:
                user_answer = print()
        if user_answer == total_chars:
            print('You are correct!')
            points +=1
        else:
            print("Sorry that's not the correct answer")
    statistics(points)




def statistics(points):
    incorrect = 10 - (points)
    print (points)
    print (incorrect)

pyramid()

Upvotes: 0

Views: 61

Answers (2)

Steven Summers
Steven Summers

Reputation: 5394

So down below is pretty much your code provided just reworked into separate functions to remove duplicated code.

Now in the code below I have commented out lines of code and given them a number, these are the options you can ( but no limited to ) take. Depending on which method you choose comment out the lines corresponding to the number and if you wish delete the others

Now, option 1 implements yield this allows you to iterate over the function ask_questions and give back the current value of points. Here you can handle the value outside the function before returning to it and continuing to ask questions.

For option 2 this will just return the final value of points and will allow you to store it and pass it into another function

from random import choice
from random import randint

def create_pyramid():
    min_pyramid_size = 3
    max_pyramid_size = 5
    num_rows = randint(min_pyramid_size, max_pyramid_size)
    pyramid_str = ''

    for i in range(num_rows):
        line = ''.join(str(choice('*%')) for j in range(2*i+1))
        pyramid_str += ' ' * (num_rows - i) + line + '\n'

    return pyramid_str

def get_input():
    """Will keep prompting user until an int is entered"""
    while True:
        user_answer = input('Enter the number of % characters in the pyramid: ')
        if user_answer.isdigit():
            return int(user_answer)
        else:
            print("Sorry, that is invalid")

def ask_questions(text, num):
    points = 0    
    for k in range (1, num + 1):
        print('\n{0} {1} of {2}'.format(text, k, num))

        pyramid = create_pyramid()
        print(pyramid)

        if get_input() == pyramid.count("%"):
            print('You are correct!')
            points += 1
##            yield points # 1
        else:
            print("Sorry that's not the correct answer")
##            yield points # 1

##    return points # 2

def statistics(points, total):
    print("Score: {0} of {1}".format(points, total))

def main():
    # 1
##    for _ in ask_questions('Practice Problem', 2):
##        pass # since we just want to ignore the points they get
##    
##    i = 1
##    for points in ask_questions('Problem', 10):
##        statistics(points, i)
##        i += 1

    # 2
##    ask_questions('Practice Problem', 2)
##    points = ask_questions('Problem', 10)
##    statistics(points) # your function code for this call

if __name__ == '__main__':
    main()

I may have not understood the question entirely so here is another example which requires return ( option 2 )

def main():

    print("Welcome to ... \n")

    ask_questions('Practice Problem', 2)
    totals = []
    while True:
        totals.append( ask_questions('Problem', 10) )
        user_input = input("Would you like to play again [Y] or [N]?")
        if user_input.lower() != 'y':
            break

    statistics(points)

Here in the top level function we have a list containing all the final scores the user got while running the program. You would have to change statistics to accommodate using a list instead of an int. But this way you can have multiple games while keeping the results of all the games they have played.

Well what I am trying to get at is have multiple functions to handle different things, generating, processing and displaying. This way you can group it all under one top-level function that can keep track of all the data.

Upvotes: 1

Tasdik Rahman
Tasdik Rahman

Reputation: 2340

A quick hack(but not the suggested way to do it) to make it work would be declare the variable points global inside the function pyramid()

So it would become

global points = 0
# and so on

Upvotes: 0

Related Questions