0

a python beginner here. My previous programming experience is with basic in the eighties, and logic programming in a proprietary system, neither of which is much help for learning python. So, to my question:

I'm writing a math quiz program (just for learning), and I've made a "main menu" by defining a function block; within it, if input is a then another func addition() is called, if input is s then func subtraction() is called and this works as intended. Within those function blocks, I'm setting a global variable quiztype to name of that function. Then I call yet another function again() from within those, to query if user wants another question of the same sort, if yes, I try to return to the relevant function with quiztype () and this fails with TypeError: 'str' object is not callable.

I did find some seemingly-related topics but either couldn't implement the answers or didn't even understand what they were talking about as I'm a beginner.

What options do I have for returning to the previously executed function?

Here's the code: (notice that variable names are not what above - different language)

from random import randint

def Alku ():
    kysy = True
    while kysy:
        lasku = input('Yhteen, Vähennys, Lopeta? ')
        if lasku == 'y':
            Yhteenlasku ()
            kysy = False
        elif lasku == 'l':
            break
            kysy = False

def Uudestaan ():
    kysy = True
    while kysy:
        samauudestaan = input('uudestaan? (k/e)? ')
        if samauudestaan == 'k':
            Lasku()
            kysy = False
        elif samauudestaan == 'e':
            Alku ()
            kysy = False

def Yhteenlasku ():
    global Lasku
    Lasku='Yhteenlasku'
    n1=(randint(1,10))
    n2=(randint(1,10))
    a1=n1+n2
    print(n1, end="")
    print(" + ", end="")
    print (n2, end="")
    print(" = ", end="")
    a2=int(input())
    print()
    if a1==a2:
        print('oikein!')
    elif a1!=a2:
        print('väärin!')
    Uudestaan()

Alku ()

And what is returned in terminal:

Traceback (most recent call last):
  File "laskut2.py", line 43, in <module>
    Alku ()
  File "laskut2.py", line 8, in Alku
    Yhteenlasku ()
  File "laskut2.py", line 41, in Yhteenlasku
    Uudestaan()
  File "laskut2.py", line 19, in Uudestaan
    Lasku()
TypeError: 'str' object is not callable
kurja
  • 123
  • 6

3 Answers3

0

You can assign function to a variable (because function is in Python first-class citizen), so effectively, for example:

def fun1():
  print("fun1")

def fun2():
  print("fun2")

def fun3():
  print("fun3")

f1 = fun1
f2 = fun2
f3 = fun3

functions = {
  "invoke_f1" : f1,
  "invoke_f2" : f2,
  "invoke_f3" : f3
}

functions["invoke_f1"]()
function_to_invoke = functions["invoke_f2"]
function_to_invoke()

yields:

fun1
fun2

More reading: https://en.wikipedia.org/wiki/First-class_function

In your specific example, modify your Uudestaan function.

def Uudestaan ():
  Lasku = Yhteenlasku                   #Add this line
  kysy = True
  while kysy:
      samauudestaan = input('uudestaan? (k/e)? ')
      if samauudestaan == 'k':
          Lasku()
          kysy = False
      elif samauudestaan == 'e':
          Alku ()
          kysy = False

because you were trying to invoke string, and this is not possible. Try to invoke type(Lasku) in your case and you'll see that it is of type str. Invoke it in function with my modification and you'll see type of function.

However I am not sure what is going on in this code, is this finnish? swedish?

jedruniu
  • 520
  • 4
  • 13
  • When implemented, this seems to return the same error message as what I originally got. On it's own it runs as stated though. – kurja May 01 '17 at 14:08
  • And how do you implement it exactly? You should refer to function itself, not to it's name as a string. Ok I see, I will examin this – jedruniu May 01 '17 at 14:12
  • This would always return me to function Yhteenlasku; that is not what I am trying to achieve. I'm trying to return to whatever function launched `Uudestaan`; that is why I have that line within function `Yhteenlasku`. In another function I would set the variable `Lasku` to whatever other value, and then `Uudestaan` would be able to send me back where I came from. ...Looks like I needed to remove the 's from `global Lasku` `Lasku = 'Yhteenlasku'` – kurja May 01 '17 at 14:33
0

We really need to see your code to see what you want to achieve but from the sound of it you want to do something like this. From the question it look like you will be recalling function within functions and returning functions, creating recursions which is not that pythonic and also will eventually throw errors and the other is not really needed in this situation. jedruniu has put really quite a good explanation on function variable assignment too.

Less robust version:

def addition():
    pass # Put code here

def subtraction():
    pass # Put code here

def menu():
    while True:
        cmd = input("Addition or subtraction? (a/s): ")
        if cmd == "a":
            addition()
        elif cmd == "s":
           subtraction()

menu()

Other version (w/ score):

def addition():
    # Put code here
    result = True
    return result # Will be added to score, so any integer or True/False

def subtraction():
    # Put code here
    result = True
    return result # Will be added to score, so any integer or True/False

def menu():
    score = 0
    while True:
        cmd = input("Addition or subtraction? (a/s/exit): ").strip().lower()
        if cmd == "exit":
            break
        elif cmd == "a":
            score += addition()
        elif cmd == "s":
            score += subtraction()
        else:
            print("Unknown option...")
      # Do something with score or return score

if __main__ == "__main__":
    menu()
Max
  • 145
  • 2
  • 15
  • I pasted this code and the first one seems to loop back to the menu (as there's nothing in 'subtraction' or 'addition' I guess) and second one returns an error, anyway returning to the menu after a question has been answered in 'subtraction' or 'addition' isn't my problem - I hope the code I added to my question helps to clarify this. – kurja May 01 '17 at 13:54
0

Your code is fine as it stands, although your global declaration is in an odd place. Still, remove the inverted comma's around your definition of Lasku which is defining it as a string and it will work.

global Lasku
Lasku=Yhteenlasku

P.S. Welcome back to programming!

In response to your question, globals would normally be declared at the beginning of your code or when the data to define becomes available but in this case you are defining it as a function, so you can't define it until the function has been defined. I guess as long as it works, where it is is fine. Personally, in this case, I'd define it here:

global Lasku
Lasku=Yhteenlasku

Alku ()
Rolf of Saxony
  • 21,661
  • 5
  • 39
  • 60