Multiple instructions in switch return statement - python

I am new to Python. Here is my question:
import sys
def main():
print "option 1) check updates 2) rewrite index 3) ..."
option = raw_input()
print "\nthe option: is: " + option
switch_option(option)
def switch_option (option):
return {
1:
# print "option is 1",
1,
2: 2
}.get(option, 0)
if __name__ == '__main__':
main()
This program works fine, but if I uncomment <print "option is 1", I get an error.
I get this error:
SyntaxError: invalid syntax.
What am I missing? I tried adding <,> and <;>.
Questions:
How can I include debug statements such as print inside a return statement?
Is the Python syntax waiting for a certain template in my case?
Does return accept multiple instructions?
Does print break the execution flow?

The short answer is that you can't use a print statement inside an expression the way you're proposing. You'd have to answer questions like "when does it get evaluated" that some languages have answers to, but not Python.
That having been said, and especially if you're new to Python but have familiarity with other functional languages, you can create a dictionary that has functions as values. Here's a way to recast your example:
#!/usr/bin/env python3
def main():
print("option 1) check updates 2) rewrite index 3) ...")
option = input().strip()
print("the option: is: " + option)
switch_option(option)
def switch_option (option):
options = {
'1': option_one,
'2': lambda: 2
}
f = options[option]
result = f()
print("the result is: " + str(result))
def option_one():
print("option is 1")
return 1
if __name__ == '__main__':
main()

I'm not sure why you're trying to put a print statement inside a dictionary
You can print before the return
def switch_option (option):
print "option is %r" ‰ option
return {
1: 1,
2: 2
}.get(option, 0)
Then you'll need to get that result
o = switch_option(option)
And yes, python supports multiple return values

Related

I want to apply unit tests to simple numeric playback code

I recently started programming with Python for the first time. I have been told that I can not access the essence of unit testing for this code. I tried to practice by listening to the importance of unit testing and Python unit testing.
The code is shown below.
# UpDown.py
import random
import unittest
servicenumber = 0
exp = 0
## Game play screen
def start_screen():
global servicenumber
exe = """
==============================
1. Up/Down Game Start
2. Exp check
3. exit
==============================
Please enter your desired service number."""
print(exe)
servicenumber = input()
if servicenumber == 1:
start_game()
elif servicenumber == 2:
check_exp()
elif servicenumber == 3:
game_exit()
else:
print "Please enter one of 1, 2, or 3."
## Up/Down This is the part of the game.
def start_game():
re = 1
global servicenumber
global exp
if servicenumber == 1:
while re != 0:
notice = """
==============================
Randomly generated values ​​are from 1 to 100.
Players should enter a number between 1 and 100.
If you win, you gain 2 exp, and if you lose, it decreases by 1.
Please enter 0 to finish.
==============================\n"""
print(notice)
var = input('input : ')
if var > 100:
print 'Please enter a value between 1 and 100.'
continue
elif var < 0:
print 'Please enter a value between 1 and 100.'
continue
elif var == 0:
re = 0
else:
print ''
randvalue = random.randrange(1,101)
if var > randvalue:
print 'Up'
exp = exp + 2
print "exp+2"
print "Your experience ",exp
print "Randomly generated values ",randvalue
continue
elif var < randvalue:
print 'Down'
exp = exp-1
print 'Decreasing story ~~'
continue
elif var == randvalue:
print 'The story of being tapped ~~'
continue
else:
print "Randomly generated values ",randvalue
continue
start_screen()
def check_exp():
global servicenumber
if servicenumber == 2:
print "Experience: ",exp
start_screen()
## (exit)
def game_exit():
global servicenumber
if servicenumber == 3:
print 'Exit'
exit()
if __name__ == "__main__":
start_screen()
else:
print "Imported. Start unit testing.\n"
And the code I tried to practice
I think it is pointless.
import unittest
import UpDownGame
class testing(unittest.TestCase):
def test_start(self):
self.assertTrue(UpDownGame.start_screen)
def test_game(self):
self.assertTrue(UpDownGame.start_game)
def test_chkexp(self):
self.assertTrue(UpDownGame.check_exp)
def test_exit(self):
self.assertTrue(UpDownGame.game_exit)
def initialize():
return testing
if __name__ == "__main__":
testsuite = (unittest.makeSuite(testing))
unittest.TextTestRunner(verbosity=2).run(testsuite)
So I want advice on unit testing.
I would really appreciate it if you let me know how to apply unit tests to this code.
Also, let me know if you think I have the basic knowledge I need.
Thank you.
The problem is that you're trying to write the tests when you've already written the code, and you've started with inherently hard to test code. If you wrote the tests before each part of code they are intended to test then you would write the code quite differently.
So, ignoring your code entirely, you want a 'start_screen' function that will print a prompt, read some input, and call a function based on that input. You don't want to hard-wire the functions that get called (because that makes it harder to test), so you might change the function so it takes a dictionary of actions and then you can pass in test actions in place of the ones the real code will run. You also don't want it reading from input() so again you might make that customisable. Writing output with print is also a bad idea for testing, as you'll want to catch the output if you need to make any assertions about it but we'll ignore that for now.
So, change def start_screen() to:
DEFAULT_ACTIONS = { 1: start_game, 2: check_exp, 3: game_exit }
def start_screen(actions=DEFAULT_ACTIONS, input=input):
pass
and write a test:
def test_start_input_1_calls_action_1(self):
calls = []
dummy_actions = { 1: lambda: calls.append('action1') }
def dummy_input():
calls.append('input')
return 1
start_screen(actions=dummy_actions, input=dummy_input)
assert calls == ['input', 'action1']
next you verify that the test compiles and runs and fails with an assertion error. If it fails for any other reason you fix the test.
Only then, you change start_screen so that the test now passes.
Then you can add other tests. A good next test would be one where the 'input' function returns 4 the first time it is called and then a 1:
def test_start_input_4_prompts_again(self):
calls = []
inputs = [1, 4]
dummy_actions = { 1: lambda: calls.append('action1') }
def dummy_input():
calls.append('input')
return inputs.pop(0)
start_screen(actions=dummy_actions, input=dummy_input)
assert calls == ['input', 'input', 'action1']
Now you verify that you get an assertion error, then you modify the code so that the test passes. Now the most important step: you look at the two tests and see that they are almost identical so you remove the duplication to another function and modify the tests so they look something like this:
def test_start_input_1_calls_action_1(self):
self.start_helper([1], ['input', 'action1'])
def test_start_input_4_prompts_again(self):
self.start_helper([4, 1], ['input', 'input', 'action1'])
def start_helper(self, inputs, expected_calls):
... add code here ...
then go on to write tests for the other functions. You will want to lose the global variable: tested functions need to be clean and not depend on variables set outside. Also that recursive call it probably the wrong thing to do, you might want to consider making start_screen have a loop and in that case the tests we just wrote will have to be updated for that.
At every step the fact that you have already written the test is going to influence how you think about the code.

Return string from Python to Shell script

I have Python code like:
x = sys.argv[1]
y = sys.argv[2]
i = sofe_def(x,y)
if i == 0:
print "ERROR"
elif i == 1:
return str(some_var1)
else:
print "OOOps"
num = input("Chose beetwen {0} and {1}".format(some_var2, some_var3))
return str(num)
After I must execute this script in shell script and return string in shell variable, like:
VAR1="foo"
VAR2="bar"
RES=$(python test.py $VAR1 $VAR2)
Unfortunately it doesn't work. The way by stderr, stdout and stdin also doesn't work due to a lot of print and input() in code. So how I can resolve my issue? Thank you for answer
That isn't even valid Python code; you are using return outside of a function. You don't wan't return here, just a print statement.
x, y = sys.argv[1:3]
i = sofe_def(x,y)
if i == 0:
print >>sys.stderr, "ERROR"
elif i == 1:
print str(some_var1)
else:
print >>sys.stderr, "OOOps"
print >>sys.stderr, "Choose between {0} and {1}".format(some_var2, some_var3)
num = raw_input()
print num
(Note some other changes:
Write your error messages to standard error, to avoid them being captured as well.
Use raw_input, not input, in Python 2.
)
Then your shell
VAR1="foo"
VAR2="bar"
RES=$(python test.py "$VAR1" "$VAR2")
should work. Unless you have a good reason not to, always quote parameter expansions.
Just use print instead of return - you bash snippet expects result on STDOUT.

Python switching the display based on input using If, Else

I want to display print text based on my Input value using IF/Else or Switch. And Also let me know how to use switch case for below code.
# OnButtonOK after clicking it, display the input value
def OnButtonOK(self):
Input = self.entrytext.get()
# self.text.insert(END, Input + '\n')
# self.scroll.config(Input = self.text.yview)
print Input
useroption = atoi(Input)
# self.OnButtonClick();
if (useroption == 1):
print "input is output"
self.SubMenu1();
else:
print "Error:Invalid"
return;
def SubMenu1(self):
print 'SubMenu1'
return;
def SubMenu2(self):
print 'SubMenu2'
return;
def SubMenu3(self):
print 'SubMenu3'
return;
I am able to print only else part:
if (useroption == 1):
print "input is output"
self.SubMenu1();
else:
print "Error:Invalid"
Let me know where exactly i am going wrong.
I think you have indentation problems in your code:
Python use 4 spaces(you can use 1 space but 4 is good practice) indentation language. Means if/else statement will be like this:
if a == 1:
print("A = 1") # 4 spaces w.r.t to above statement
elif a == 2:
print("A = 2")
elif a ==3:
print("A = 4")
else:
print("A = pta nahi")
you can use above if/else statements as a switch case and also your indentation problem will be solved
It's a simple beginner's mistake, you're indenting it worng:
if (useroption == 1):
print "input is output"
self.SubMenu1();
else:
print "Error:Invalid"
should be
if (useroption == 1):
print "input is output" # You had an indent too many here
self.SubMenu1();
else:
print "Error:Invalid"
Python is indentation sensitive; too many or too few indentations will break your code.

Python console menu using a dictionary

I'm building a Windows application using Python 2.7 that requires a simple console menu, ex:
Do something
Do something else
Exit
There will be several menus, the main menu will link to others. So I am attempting to avoid the scenario of having a bunch of stacks of if input == "1" code. Similar to this StackOverflow link. My below code is currently skipping the main menu and executing every option in my second menu. I've looked it over but I'm failing to see the logic in why it is performing the way it does.
computer = ""
# need a class for each of the options in power_menu
class power:
def logoff(self, computer):
print "logging off " + computer
def restart(self, computer):
print "restarting " + computer
def shutdown(self, computer):
print "shutting down " + computer
def set_computer():
global computer
#os.system("cls")
# optionally print the banner
computer = raw_input("Computer: ")
# check the computer is online
# move to the main menu with the computer parameter
menu().menu_main(computer)
def func_quit():
sys.exit()
def invalid(computer):
#os.system("cls")
print "INVALID CHOICE!"
menu().menu_main(computer)
class menu():
def menu_main(self, computer):
opts_main = {"1":("Power Options", self.menu_power(computer)),
"2":("Service Options", self.menu_service(computer)),
"3":("Service Tag & Warranty", self.menu_warranty(computer)),
"4":("User Options", self.menu_user(computer)),
"5":("Change Computer", set_computer),
"6":("Quit hd-con", func_quit)
}
for key in sorted(opts_main.keys()):
print "\t" + key + ": " + opts_main[key][0]
ans = raw_input("Selection: ")
try:
opts_main.get(ans, [None, invalid])[1]()
except Exception, e:
print e
#men_sel()
def menu_power(self, computer):
opts_power = {"1":("Logoff", power().logoff(computer)),
"2":("Restart", power().restart(computer)),
"3":("Shutdown", power().shutdown(computer)),
"4":("Main Menu", menu.menu_main),
"5":("Quit hd-con", func_quit)
}
for key2 in sorted(opts_power.keys()):
print "\t" + key2+": " + opts_power[key2][0]
ans2 = raw_input("Selection: ")
try:
opts_power.get(ans2)[1]()
#pow_sel()
except:
raise
My output for the above is looking like this.
Computer: asdf
logging off asdf
restarting asdf
shutting down asdf
1: Logoff
2: Restart
3: Shutdown
4: Main Menu
5: Quit
Selection:
I'm looking for guidance on using a dictionary for use in a console menu, fixes for the existing code, or a recommended direction to take this instead of what i'm looking at.
Thanks in advance.
Your assignment to the dictionary:
opts_main = {"1":("Power Options", self.menu_power(computer)), ...}
is calling menu_power, and storing the return value (None) in the tuple. You can use e.g. functools.partial to avoid this:
from functools import partial
opts_main = {"1":("Power Options", partial(self.menu_power, computer)), ...}

Simple Phonebook

this is some simple code I wrote for a phonebook.
It does not seem to work though, and I do not know why.
I am very new to python, and I am sure there are many errors.
def startup(contactlist = {}):
print "Welcome to Contacts+\n"
print "Please enter your name"
name = raw_input()
print "Hi " + name + " would you like to check your existing contacts or make new ones?"
print "To make new contacts type in 'New'"
print "To check existing contacts type in 'Contacts'"
choose = ""
choose = raw_input()
if choose == "'New'" or choose == "'new'" or choose == "New" or choose == "new":
newcontact()
elif choose == "'Contacts'" or choose == "'contacts'" or choose == "Contacts" or choose == "contacts":
checkcontact()
def newcontact():
startup(contactlist = {})
print "To create a new contact please first input the name"
contactname = raw_input()
print "Next enter the phone number"
contactnumber = raw_input()
print "Contact created!"
contactlist[name] = number
def checkcontact():
startup(contactlist = {})
print contactlist
startup()
Have you tried to run this...?
This if/elif statement shouldn't be indented:
if choose == "'New'" or choose == "'new'" or choose == "New" or choose == "new":
newcontact()
elif choose == "'Contacts'" or choose == "'contacts'" or choose == "Contacts" or choose == "contacts":
checkcontact()
And why do you have:
startup(contactlist = {})
in the beginning of newcontact() and checkcontact() function?
Four things you can do right now to make your code better:
Go read about this gotcha in Python. We tricked you. (We're sorry! We had good reasons.) You can't really do that with lists and dicts, and you have to use a Python idiom involving None to do it right.
Use raw_input's first argument. Instead of print('Hey user!'); raw_input(), just write raw_input('Hey user!').
Learn the in keyword. Whenever you find yourself saying if x == 'x' or x == 'y' or x == 'z', it's probably easier to write if x in 'xyz' (strings are iterable, remember?). You can also get rid of two of those cases by stripping off quotes the user might enter if you don't want them -- choose.strip("'").
Fix your function calls. Functions in Python can be called in two ways, using positional arguments f(a, b, c) or keyword arguments f(a, b=0, c=2). Calls like startup(contactlist={}) are just explicitly setting that argument to the empty dict, its default value, so this is always equivalent to startup() the way you have it defined.

Categories

Resources