MyMenu using dictionaries

I’m learning Python though the book Software Development 1: with Python by Tom Baugh. Unfortunately it appears a bit outdated. I’m having trouble with getting the following code to not give an error. Any help with this would be greatly appreciated.

‘’’
import math

class MenuCommand:

# Class to manage menu commands

def __init__(self, fnCmdHandler, dictMenu, strCmd, bShouldExit = False):  # 

    self.fnCmdHandler = fnCmdHandler

    self.strCmd = strCmd

    dictMenu[strIn] = self

    self.bShouldExit = bShouldExit

# end def __init__

def compareCmd(self, strCmd):

    return strCmd == self.strCmd

# end def

def Execute(self):

    self.fnCmdHandler()

# end def

def ShouldExit(self):

    return self.bShouldExit

# end def

#end class

def PromptCommand():

# Prompts the console user, and returns the string of typed text

strIn=input("Enter command: ")

return strIn

end def

def Cmd_CalculateSine():

# Prompts the user for a degrees parameter, then calculates

# the sine and prints the result to the console.

strIn = input("Enter angle in degrees > ")

fDegrees = float(strIn)

fSine = math.sin(math.radians(fDegrees))

print("sin(", fDegrees, ") =", fSine)

Menu()

end def

def Cmd_CalculateCosine():

# Prompts the user for a degrees parameter, then calculates

# the cosine and prints the result to the console.

strIn = input("Enter angle in degrees > ")

fDegrees = float(strIn)

fCosine = math.cos(math.radians(fDegrees))

print("cos(", fDegrees, ") =", fCosine)

Menu()

end def

def Cmd_CalculateSquareRoot():

# Prompts the user for a parameter, then calculates

# the square root and prints the result to the console.

strIn = input("Enter squared value > ")

fSquared = float(strIn)

fSquareRoot = math.sqrt(fSquared)

print("Square root of", fSquared, " =", fSquareRoot)

end def

def Cmd_DisplayMenu():

# Displays the program menu

print("")

print("Available commands")

print("? - display this menu")

print("c - cosine of angle in degrees")

print("q - square root")

print("s - sine of angle in degrees")

print("x to exit")

print("")

end def

def Cmd_Exit():

# Exits the program

print("Bye!")

quit()

end def

def Menu():

while True:

    strIn = PromptCommand()

    objCmd = GetMenuCommand(strIn)

    if None == objCmd: continue

    objCmd.Execute()

    if objCmd.ShouldExit(): break                

# end while

def GetMenuCommand(strIn):

return m_dictCmds[strIn]     

end def

m_objCmdCalculateSine = MenuCommand(Cmd_CalculateSine, ‘s’)

m_objCmdDisplayMenu = MenuCommand(Cmd_DisplayMenu, ‘?’)

m_objCmdCalculateCosine = MenuCommand(Cmd_CalculateCosine, ‘c’)

m_objCmdCalculateSquareRoot = MenuCommand(Cmd_CalculateSquareRoot, ‘q’)

m_objCmdExit = MenuCommand(Cmd_Exit, ‘x’, True)

m_dictCmds = {}

MenuCommand(Cmd_DisplayMenu, m_dictCmds, ‘?’),

MenuCommand(Cmd_CalculateCosine, m_dictCmds, ‘c’),

MenuCommand(Cmd_CalculateSquareRoot, m_dictCmds, ‘q’),

MenuCommand(Cmd_CalculateSine, m_dictCmds, ‘s’),

MenuCommand(Cmd_Exit, m_dictCmds, ‘x’, True)

Menu()
‘’’

The error given:
Traceback (most recent call last):
File “c:\Users\Chris_M\DevPython\MyMenu.rev1.8.5.20.21.py”, line 94, in
m_objCmdCalculateSine = MenuCommand(Cmd_CalculateSine, ‘s’)
TypeError: init() missing 1 required positional argument: ‘strCmd’

I’ve trimmed the code below for clarity. Comments inline below.

import math

class MenuCommand:
    # Class to manage menu commands
    def __init__(self, fnCmdHandler, dictMenu, strCmd, bShouldExit = False):  #
        self.fnCmdHandler = fnCmdHandler
        self.strCmd = strCmd
        dictMenu[strIn] = self
        self.bShouldExit = bShouldExit
[...]
def Menu():
    while True:
        strIn = PromptCommand()
        objCmd = GetMenuCommand(strIn)
        if None == objCmd: continue
        objCmd.Execute()
        if objCmd.ShouldExit(): break
    # end while

def GetMenuCommand(strIn):
    return m_dictCmds[strIn]

m_objCmdCalculateSine = MenuCommand(Cmd_CalculateSine, 's')
m_objCmdDisplayMenu = MenuCommand(Cmd_DisplayMenu, '?')
m_objCmdCalculateCosine = MenuCommand(Cmd_CalculateCosine, 'c')
m_objCmdCalculateSquareRoot = MenuCommand(Cmd_CalculateSquareRoot, 'q')
m_objCmdExit = MenuCommand(Cmd_Exit, 'x', True)

m_dictCmds = {}
MenuCommand(Cmd_DisplayMenu, m_dictCmds, '?'),
MenuCommand(Cmd_CalculateCosine, m_dictCmds, 'c'),
MenuCommand(Cmd_CalculateSquareRoot, m_dictCmds, 'q'),
MenuCommand(Cmd_CalculateSine, m_dictCmds, 's'),
MenuCommand(Cmd_Exit, m_dictCmds, 'x', True)

Menu()

Let’s look at your error:

**The error given:**
Traceback (most recent call last):
  File "c:\Users\Chris_M\DevPython\MyMenu.rev1.8.5.20.21.py", line 94, in <module>
    m_objCmdCalculateSine = MenuCommand(Cmd_CalculateSine, 's')
TypeError: __init__() missing 1 required positional argument: 'strCmd'

You’re creating an instance of MenuCommand, handing it an
implemenetation function Cmd_CalculateSine and an action command string
‘s’. Python’s complaining that strCmd is omitted (it would normally be
the ‘s’).

Look at the definition of MenuCommand.init:

def __init__(self, fnCmdHandler, dictMenu, strCmd, bShouldExit = False):

It also expects a dictMenu parameter, which I imagine should be
m_dictCmds from the code above.

Because that is omitted, ‘s’ is passed for dictMenu, with nothing
available for strCmd, hence the error.

Try this instead:

m_objCmdCalculateSine = MenuCommand(Cmd_CalculateSine, m_dictCmds, 's')

Note that you will have to move the definition of m_dictCmds to above
this call, otherwise it won’t yet exist.

Cheers,
Cameron Simpson cs@cskk.id.au

1 Like

Thank you so much Cameron. Trying things out now and looking it over to ensure I understand the resolution. I really appreciate the help.

Just tested. Once again, thank you so much Cameron. Works perfect and I totally appreciate the explanation as well. I see why it wouldn’t work now.