How could I improve this code to make it shorter and more functional?
#!usr/bin/python
import time
integer = 0
print("The current integer is set at " + str(integer) + ".")
print("\n")
time.sleep(2)
prompt = raw_input("Would you like to change the integer? (Y/N) ")
print("\n")
if prompt == 'y':
integer = int(raw_input("Insert the new integer here: "))
print("\n")
print("You have changed the integer to " + str(integer) + ".")
print("\n")
print("\n")
time.sleep(1)
print("1. Add / 2. Subtract / 3. Multiply / 4. Divide")
print("\n")
new_int = raw_input("What would you like to do with your new integer? (Choose a number) ")
print("\n")
if new_int == '1':
added_int = int(raw_input("What number would you like to add to your integer (" + str(integer) + ") by?"))
outcome1 = integer + added_int
print("\n")
print("The sum of " + str(integer) + " + " + str(added_int) + " is " + str(outcome1))
if new_int == '2':
subtracted_int = int(raw_input("What number would you like to subtract your integer (" + str(integer) + ") by?"))
outcome2 = integer - subtracted_int
print("\n")
print("The difference of " + str(integer) + " - " + str(subtracted_int) + " is " + str(outcome2))
if new_int == '3':
multiplied_int = int(raw_input("What number would you like to multiply your integer (" + str(integer) + ") by?"))
outcome3 = integer * multiplied_int
print("\n")
print("The product of " + str(integer) + " x " + str(multiplied_int) + " is " + str(outcome3))
if new_int == '4':
divided_int = int(raw_input("What number would you like to divide your integer (" + str(integer) + ") by?"))
outcome4 = integer / divided_int
print("\n")
print("The quotient of " + str(integer) + " / " + str(divided_int) + " is " + str(outcome4))
elif prompt == "n":
print("The integer will stay the same.")
time.sleep(2)
print("Press any key to exit...")
else:
print("Invalid input.")
raw_input()
3 Answers 3
Here is a less verbose script that does the basic operations like you are doing. It may be a little advanced for you based on what you wrote, but I thought you might be interested in having a look.
import re
pat = re.compile(r'\s*(\-?\d+\.?\d*)\s*([+-/*])\s*(\-?\d+\.?\d*)\s*')
while True:
print 'Input a basic expression (ex: 12 * 4, 3.24+3, 19/2, etc) or -1 to exit:'
user_input = raw_input()
if user_input == '-1':
break
m = pat.match(user_input)
if m:
try:
result = eval(m.group())
except ZeroDivisionError:
print 'Cannot divide by zero.',
continue
print m.group(1), m.group(2), m.group(3), '=', result
else:
print 'Invalid expression.',
Sample Output from running the script:
>>>Input a basic expression (ex: 12 * 4, 3.24+3, 19/2, etc) or -1 to exit:
-2 * 1
-2 * 1 = -2
Input a basic expression (ex: 12 * 4, 3.24+3, 19/2, etc) or -1 to exit:
-4 / 0
Cannot divide by zero. Input a basic expression (ex: 12 * 4, 3.24+3, 19/2, etc) or -1 to exit:
5 /2
5 / 2 = 2
Input a basic expression (ex: 12 * 4, 3.24+3, 19/2, etc) or -1 to exit:
5/2.0
5 / 2.0 = 2.5
Input a basic expression (ex: 12 * 4, 3.24+3, 19/2, etc) or -1 to exit:
78-ひく-ひく2
78 -ひく -ひく2 =わ 80
Input a basic expression (ex: 12 * 4, 3.24+3, 19/2, etc) or -1 to exit:
90+2
90 + 2 = 92
Input a basic expression (ex: 12 * 4, 3.24+3, 19/2, etc) or -1 to exit:
-1
>>>
Here's a little breakdown in case you don't understand what's going on. The script uses regular expressions, hence import re
, to extract a simple equation. A simple equation meaning a number followed by an operation followed by another number.
'\s*(\-?\d+\.?\d*)\s*([+-/*])\s*(\-?\d+\.?\d*)\s*'
is the regular expression.
\s* means 0 or more spaces
\-? means there may or may not be a - (for negative numbers)
\d+ means 1 or more digits
\.? means there may or may not be a . (for decimal numbers)
\d* means 0 or more digits
[+-/*] means one of those symbols
So lets look at what is being grouped in the brackets ()
(\-?\d+\.?\d*) which means a positive or negative number that could be an integer or a decimal
([+-/*]) which picks the operation to be performed on the numbers
(\-?\d+\.?\d*) which is the same as the first
Each of these expressions in brackets are separated with a \s*
and since match(string)
only keeps what's in the brackets, all the spacing is ignored.
The regular expression is then compiled and you can use that pattern variable (which I called pat
) to match against input (which I stored in m
in the line m = pat.match(user_input)
).
As I said above, match
only keeps what's in the brackets, and it puts them into groups.
m.group(0) #is everything ex) 10*10.5
m.group(1) #is the first brackets contents. ex) 10
m.group(2) #is the second brackets contents. ex) *
m.group(3) #is the third brackets contents. ex) 10.5
You can see how I printed out the equation with the result using m.group()
. Also, I should say that when match(input)
doesn't find a match, it returns None
so if m:
in the code passes if a match is found and fails if one isn't.
Finally, eval()
will evaluate the expression inside of it which is how we get the result.
You can also see that I used a try/except
statement to catch division by zero. Oh and if you put an r in front of a string like r'hello world\n'
, it is a "raw string" and ignores escaped characters (ie: things like new line \n) and just stores the characters as is.
Even if this isn't exactly what you were looking for, I hope you found it interesting and perhaps learned something from it.
How about something like this?
import time
def add_num(x):
added_int = int(raw_input("What number would you like to add to your integer (%s) by?" % x))
outcome = x + added_int
print("\nThe sum of %s + %s is %s" % (x, added_int, outcome))
return outcome
def sub_num(x):
sub_int = int(raw_input("What number would you like to subtract to your integer (%s) by?" % x))
outcome = x - sub_int
print("\nThe subtract of %s - %s is %s" % (x, added_int, outcome))
return outcome
def mul_num(x):
mul_int = int(raw_input("What number would you like to multiply your integer (%s) by?" % x))
outcome = x * mul_int
print("\nThe multiplication of %s * %s is %s" % (x, added_int, outcome))
return outcome
def div_num(x):
div_num = int(raw_input("What number would you like to divide your integer (%s) by?" % x))
outcome = x / float(div_num)
print("\nThe divider of %s / %s is %s" % (x, added_int, outcome))
return outcome
def main():
op_map = {"1":add_num, "2":sub_num, "3":mul_num, "4":div_num}
number = 0
print("The current integer is set at %s ." % number)
while True:
prompt = raw_input("Would you like to change the number? (Y/N)").lower()
if prompt == "y":
number = int(raw_input("Insert the new integer here: "))
print("\nYou have changed the integer to %s .\n\n" % number)
time.sleep(1)
print("1. Add / 2. Subtract / 3. Multiply / 4. Divide\n")
op = raw_input("What would you like to do with your new integer? (Choose a number) \n")
if op is not None:
operation = op_map.get(op)
number = operation(number)
elif prompt == "n":
print("The integer will stay the same.")
time.sleep(2)
raw_input("Press enter key to exit...")
break
else:
print("Invalid response")
if __name__ == '__main__':
main()
-
\$\begingroup\$ You shouldn't define a function
div_num()
and then inside it use a variable also calleddiv_num
\$\endgroup\$Matt– Matt2012年10月29日 12:37:20 +00:00Commented Oct 29, 2012 at 12:37 -
\$\begingroup\$ @Matt eh good spot but really? function local namespace rarely matters. \$\endgroup\$Jakob Bowyer– Jakob Bowyer2012年10月29日 20:24:42 +00:00Commented Oct 29, 2012 at 20:24
-
3\$\begingroup\$ It makes the code harder to understand if you use the same name for two different things like that. In general it is bad practice. \$\endgroup\$Matt– Matt2012年10月29日 22:28:29 +00:00Commented Oct 29, 2012 at 22:28
@Jackob wrote a better solution, but I can still see much duplication, here you can see a DRY version using higher order functions:
def user_interface_operation(start, operation):
b = int(raw_input("What is x in {} {} x ?".format(start, operation.__name__)))
outcome = operation(start, b)
print("The result is {}".format(outcome))
return outcome
add_num = lambda start: user_interface_operation(start, op.add)
sub_num = lambda start: user_interface_operation(start, op.sub)
mul_num = lambda start: user_interface_operation(start, op.mul)
div_num = lambda start: user_interface_operation(start, op.div)