So why result doesn't change? result is global but it will return zero even when print(result) in def add() print correct answer.
number = int(input("enter your first num: "))
operation = input("enter your operation: ")
second_number = int(input("enter your second num: "))
def cal(num1,op,num2):
result = 0
def add():
result = num1+num2
print(result)
def multiply():
result = num1 * num2
def devide():
if not num2==0:
result = num1 / num2
else:
result = 'num2 can\'t be zero'
def default():
print("Incorrect option")
switch = {
'+':add,
'*':multiply,
'/':devide
}
switch.get(op,default)()
return result
print(cal(number,operation,second_number))
The global result was outside the scope.
number = int(input("enter your first num: "))
operation = input("enter your operation: ")
second_number = int(input("enter your second num: "))
def cal(num1, op, num2):
def add():
result = num1+num2
return result
def multiply():
result = num1 * num2
return result
def devide():
if not num2 == 0:
result = num1 / num2
return result
else:
result = 'num2 can\'t be zero'
return result
def default():
print("Incorrect option")
switch = {
'+': add,
'*': multiply,
'/': divide
}
return switch.get(op, default)()
print(cal(number, operation, second_number))
Python program that uses global
def method():
# Change "value" to mean the global variable.
# ... The assignment will be local without "global."
global value
value = 100
value = 0
method()
# The value has been changed to 100.
print(value)
100`
Python program that uses nonlocal
def method():
def method2():
# In nested method, reference nonlocal variable.
nonlocal value
value = 100
# Set local.
value = 10
method2()
# Local variable reflects nonlocal change.
print(value)
# Call method.
method()
100
The result variables in the operation functions are in a different scope to the cal function. Have those functions return a value and then return that from cal and you will get the desired behaviour.
def cal(num1,op,num2):
def add():
return num1+num2
def multiply():
return num1 * num2
def devide():
if not num2==0:
result = num1 / num2
else:
result = 'num2 can\'t be zero'
return result
def default():
print("Incorrect option")
switch = {
'+':add,
'*':multiply,
'/':devide
}
return switch.get(op,default)()
Related
Sorry to ask a very long question but I am very new to Python. I started a free course on FutureLearn and a task was to create a calculator. The code I had ended up being a lot longer than other answers and it was too big to fit into the comment section. Just looking for tips for any part of my code that could be squished down. First question on StackOverflow so I'm sorry if this is a bad question.
def main():
operations = ['multiplication', 'division', 'addition', 'subtraction', 'x^y']
def find_op():
while True:
try:
operation = input('What do you want to do? Addition, subtraction, multiplication, division, or x^y??\n')
operations.index(operation.lower())
break
except ValueError:
input('Error!, you must input one of the five options, enter to try again.')
return operations.index(operation.lower())
operation_index = find_op()
match operation_index:
case 0:
num_question_ending = 'multiply with'
case 1:
num_question_ending = 'divide with'
case 2:
num_question_ending = 'add with'
case 3:
num_question_ending = 'subtract with'
case 4:
num_question_ending = 'create an exponential with'
def add():
add_ans = global_number1 + global_number2
print(f'{global_number1} + {global_number2} =\n{add_ans}')
def sub():
sub_ans = global_number1 - global_number2
print(f'{global_number1} - {global_number2} =\n{sub_ans}')
def mult():
mult_ans = global_number1 * global_number2
print(f'{global_number1} multiplied by {global_number2} =\n{mult_ans}')
def div():
while True:
try:
div_ans = global_number1 / global_number2
break
except ZeroDivisionError:
input('Naughty naughty boy trying to divide by 0. '
'Now you gonna have to restart the code. Press enter plz')
main()
print(f'{global_number1} divided by {global_number2} =\n{div_ans}')
def power():
if global_number1 == 0 and global_number2 == 0:
input('Naughty boy trying 0^0, dat is undefined boi. Enter to restart the whole thing.')
main()
pow_ans = global_number1 ** global_number2
print(f'{global_number1} to the power of {global_number2} =\n{pow_ans}')
def get_number1():
while True:
try:
numba1 = input(f'what\'s the first number you want to {num_question_ending}??\n')
float(numba1)
break
except ValueError:
input('input must be a number. enter to try again.')
numba1 = float(numba1)
return numba1
def get_number2():
while True:
try:
numba2 = input(f'what\'s the second number you want to {num_question_ending}??\n')
float(numba2)
break
except ValueError:
input('input must be a number. enter to try again.')
numba2 = float(numba2)
return numba2
global_number1 = get_number1()
global_number2 = get_number2()
match operation_index:
case 0:
mult()
case 1:
div()
case 2:
add()
case 3:
sub()
case 4:
power()
def repeat():
go_again_ans = input('would you like to go again? Y/N\n')
if go_again_ans == 'Y':
main()
elif go_again_ans == 'N':
exit()
else:
input('Error! You need to answer with either Y or N, enter to try again.')
repeat()
repeat()
if __name__ == '__main__':
main()
I think this is the most concise way
I used the menu prompt to save the text, first class functions to not search for the operation and a lambda functions to avoid defining each function in 3 lines, also not checking for the zero I only catch the exception
I am also still learning so excuse me if something is off
Thanks
menu_prompt = f"""
Please enter:
'a' For addition
's' For Subtraction
'm' For Multiplication
'd' For Division
'p' For Exponential operations
'q' To quit
"""
add = lambda x, y: f"{x} + {y} = { x + y}"
subtract = lambda x, y: f"{x} - {y} = { x - y}"
multiply = lambda x, y: f"{x} * {y} = { x * y}"
divide = lambda x, y: f"{x} / {y} = { x / y:.2f}"
power = lambda x, y: f"{x} ^ {y} = { x ** y}"
operations = {
'a': add,
's': subtract,
'm': multiply,
'd': divide,
'p': power
}
def get_number(order):
while True:
try:
return float(input(f"Please enter the {order} number: "))
except ValueError:
print("Please enter a valid number")
def run_selected_operation(operation):
x = get_number("first")
y = get_number("second")
try:
print(operation(x, y))
except ZeroDivisionError:
print("Can not divide by zero, try again")
user_selection = input(menu_prompt)
while user_selection.lower() != 'q':
if user_selection in operations:
selected_operation = operations[user_selection]
run_selected_operation(selected_operation)
else:
print("Please enter a valid selection")
user_selection = input(menu_prompt)
user_selection = input(menu_prompt)
print(menu_prompt)
A programme that check if the user input number is divisible by 7. No error until I run and enter the number, then I receive a number of errors. where is the mistake, please?
def inputdata():
userinput=float(input("Enter number:"))
return userinput
def processdata (userinput):
reminder=userinput % 7
if reminder==0:
result=True
return result
else:
result=False
return result
def outputdata(result):
if result==True:
answer=(print("It is dividable by 7"))
return answer
if result==False:
answer=(print("It is not dividable by 7"))
return answer
def main():
inputdata()
processdata(inputdata)
outputdata(processdata)
I have edited the main part.
There were some problems with the main()
def inputdata():
userinput=float(input("Enter number:"))
return userinput
def processdata (userinput):
reminder=userinput % 7
if reminder==0:
result=True
return result
else:
result=False
return result
def outputdata(result):
if result==True:
answer=(print("It is dividable by 7"))
return answer
if result==False:
answer=(print("It is not dividable by 7"))
return answer
def main():
inp = inputdata() # <---------
pr_data = processdata(inp) # <-------------
outputdata(pr_data)
Enter number:21
It is dividable by 7
Enter number:2
It is not dividable by 7
One liner Solution:
g = lambda x: "It is not dividable by 7" if x%7 else "It is dividable by 7"
g(int(input("Enter Number: ")))
Enter Number: 12
It is not dividable by 7
Try
def divisible(x):
return x % 7 == 0
userinput = int(input())
if divisible(userinput):
print('Case true')
else:
print('Case false')
Note that answer=(print("It is dividable by 7")) is not valid in python since print returns a None value
I don't think you are passing parameters correctly in main(). You have:
def main():
inputdata()
processdata(inputdata)
outputdata(processdata)
but (crudely) what might work is
def main():
outputdata(processdata(inputdata()))
I think your program is a bit to complicated in terms of the number of functions your using. Also your input wasn't converted into a integer in order to perform the calculation:
def trydivision(promt):
"""Test if what is given from the user is divisible by 7"""
try:
value = int(promt) % 7
if value == 0:
print("Yes, " + str(promt) + " is divisible by 7.")
print("The result is " + str(value))
else:
print("The number " + str(promt) + " is not divisible by 7.")
except ValueError:
print("Please type an integer and not a string!")
promt = input("Enter Number: ")
trydivision(promt)
If it possible to pass a >= sign through a parameter: As in:
def example():
num1 = 0
num2 = 5
sign1 = >=
sign2 = <=
test(num1, num2, sign1, sign2)
def test(num1, num2, sign1):
while num1 sign1 0 and num2 sign2 5:
print('whatever')
num1+=1
num2-=1
Obviously this isn't what I'm really trying to do; I was just wondering if it was possible...
Yes it is possible using the operator module. However they are treated as functions and not strings which is what they appear to be in your original attempt.
from operator import le, ge
def example():
num1 = 0
num2 = 5
sign1 = ge
sign2 = le
def test(num1, num2, sign1, sign2):
while sign1(num1, 0) and sign2(num2, 5):
print('whatever')
num1+=1
num2-=1
I'm programming a single line calculator in python. It needs to be able to take in an expression of any length and with multiple operators. It then returns the answer while following the order of operations.
i.e. "2 / 4 - 2 * 3 + 4" and it returns -1.5
This is what I have so far
def findNextOpr(s): #DONE
#this function is used to find the next operator in the string s
if len(s)<=0 or not isinstance(s,str):
print("type mimatch error: findNextOpr")
return "type mimatch error: findNextOpr"
s = list(s) #converts s to a list
operator = ["+", "-", "/", "*"]
for i in s:
if i in operator:
return i
else:
return -1
def isNumber(s): #DONE
#this function is used to check if it's a number
#checks if string s meets the requirements
if len(s)==0 or not isinstance(s, str):
print("type mismatch error: isNumber")
return "type mismatch error: isNumber"
#strip string of all whitespace.
s = s.strip(" ")
s = s[0:] #removes minus signs but only from the front of string
try: #checks to make sure s2 is a number and doesn't have more than 1 period
s=float(s)
return True
except:
return False
def getNextNumber(expr, pos): #DONE
#checks to make sure expr and pos match the requirements. returns error if they don't
if len(expr)==0 or not isinstance(expr, str) or pos<0 or pos>=len(expr) or not isinstance(pos, int):
print("type mismatch error: getNextNumber")
return None, None, "type mismatch error: getNextNumber"
s = expr[pos:] #sets string1 equal to position that was passed
op=['-','+','*','/']
newOpr = findNextOpr(s) #newOpr equals left-most operator, calls findNext to achieve this
if newOpr in op:
if expr.find(newOpr,pos)>=pos:
oprPos=expr.find(newOpr,pos)
else:
newOpr=None
if newOpr==None:
oprPos = None
if isNumber(expr[pos:oprPos]): #checks to make sure if string is actually a #
newNumber = float(expr[pos:oprPos])
else:
newNumber = None #if it is a #, assigns value to newNumber
return newNumber, newOpr, oprPos
def exeOpr(num1, opr, num2):
#This is a simple utility function skipping type check
if opr=="+":
return num1+num2
elif opr=="-":
return num1-num2
elif opr=="*":
return num1*num2
elif opr=="/":
return num1/num2
else:
return None
def calc(expr):
#the below line checks if expr is a string
if not isinstance(expr, str) or len(expr) <= 0:
print("argument error: line A in eval_expr")
return "argument error: line A in eval_expr"
#below line creates three variables
#sets them equal to whatever is returned by the getNextNumber function
#the getNextNumber function is called. It passes the expr and integer 0
newNumber, newOpr, oprPos = getNextNumber(expr, 0)
#if newNumber is none, return error
#if newOpr is none, return newNumber
#if newOpr is add/sub set mode=add, create addResult=newNumber and mulResult = None
#if newOpr is mult/div set mode=mul, crate addResult=0 and mulResult=newNumber
if newNumber is None:
print("input formula error: line B in eval_expr")
return "input formula error: line B in eval_expr"
elif newOpr is None:
return newNumber
elif newOpr=="+" or newOpr=="-":
mode="add"
addResult=newNumber #saves # at first index to addResult if 1st operator is + or -
mulResult=None
elif newOpr=="*" or newOpr=="/":
mode="mul"
addResult=0
lastOpr = "+"
mulResult=newNumber #saves # at first index to mulResult if 1st operator is + or -
#pos and opr are created
pos=oprPos+1 #current positon
opr=newOpr #current operator
while True:
newNumber, newOpr, oprPos = getNextNumber(expr, pos)
#--- code while loop ---#
while True:
newNumber, newOpr, oprPos=getNextNumber(expr, pos)
#if expr[pos:] == " 3- 2*1":
# pdb.set_trace()
if newNumber== None and pos>=len(expr):
return "Expression error"
elif newOpr== None and mode=='add':
return exeOpr(addResult, opr, newNumber)
elif newOpr== None and mode=='mul':
return exeOpr(mulResult, opr, newNumber)
elif (newOpr== "+" or newOpr=='-') and mode=='add' :
addResult= exeOpr(addResult,opr,newNumber)
pos= oprPos+1
opr=newOpr
elif (newOpr=="*" or newOpr=='/') and mode=='add':
addResult= newNumber
lastOpr= opr
mulResult= exeOpr(addResult,newOpr, newNumber)
mode='mul'
pos= oprPos+1
opr=newOpr
elif (newOpr=="*" or newOpr=="/") and mode=="mul":
mulResult= exeOpr(mulResult, opr, newNumber)
pos= oprPos+1
opr=newOpr
elif (newOpr=="-" or newOpr=='+') and mode=="mul":
mulResult=exeOpr(mulResult,opr, newNumber)
addResult= exeOpr(mulResult, lastOpr, newNumber)
mode="add"
pos= oprPos+1
opr=newOpr
#--- end of function ---#
expr = "2 / 4 - 2 * 3 + 4"
print(calc(expr))
Everything works except the output. When I run the program I get an answer of 13.0
I know the error is in the calc function. Can anyone figure out what I'm doing wrong.
Thanks.
Your calc is not working as you expected
HINT:
def exeOpr(num1, opr, num2):
#This is a simple utility function skipping type check
if opr=="+":
print "{} + {}".format(num1, num2)
return num1+num2
elif opr=="-":
print "{} - {}".format(num1, num2)
return num1-num2
elif opr=="*":
print "{} * {}".format(num1, num2)
return num1*num2
elif opr=="/":
print "{} / {}".format(num1, num2)
return num1/num2
else:
return None
OUTPUT
2.0 / 4.0
0.5 + 4.0
2.0 * 2.0
4.0 * 3.0
12.0 - 3.0
9.0 + 4.0
13.0
I have a problem with my RPN calculator:
def calculate_onp(onp):
from stack.stack import Stack
OPERATORS = ['+', '-', '*', '/']
s = Stack()
lista = onp.split(" ")
index = None
for i in range(1, len(onp)):
index = i - 1
if lista[index] in OPERATORS:
if lista[index] == OPERATORS[0]:
num1 = s.pop()
num2 = s.pop()
wyn = int(num1) + int(num2)
s.push(wyn)
elif lista[index] == OPERATORS[1]:
num1 = s.pop()
num2 = s.pop()
wyn = int(num1) - int(num2)
s.push(wyn)
elif lista[index] == OPERATORS[2]:
num1 = s.pop()
num2 = s.pop()
wyn = int(num1) * int(num2)
s.push(wyn)
elif lista[index] == OPERATORS[3]:
num1 = s.pop()
num2 = s.pop()
wyn = int(num1) / int(num2)
s.push(wyn)
else:
return 'ERROR'
else:
s.push(lista[index])
return int(s.pop())
I added a stack implementation to this:
from stack.exceptions import ElementDoesNotExist
class Stack(object):
def __init__(self):
self.stack = []
def __len__(self):
return len(self.stack)
def push(self, s):
return self.stack.append(s)
def pop(self):
if len(self.stack) == 0:
raise ElementDoesNotExist
else:
return self.stack.pop()
def show_list(self):
print(self.stack)
And exceptions:
for stack:
class ElementDoesNotExist(Exception):
pass
for rpn:
class OnpException(Exception):
pass
class OnpMissingOperationArgument(OnpException):
pass
class OnpMissingNumericArgument(OnpException):
pass
After running this:
File "/home/maciek/PycharmProjects/Calc/stack/stack.py", line 16, in pop
raise ElementDoesNotExist
stack.exceptions.ElementDoesNotExist
What's wrong?
your pop function has called to a function named len(self.stack). But It doesn't exists. so try on Changing the name def __len__(self): to def len(self):