AttributeError: 'Fraction' object has no attribute 'denom' - python

The below code is part of a fraction calculator, I want my code to go to my gcd function from my init so that I can pass the result as a gcd of the fraction to simplify it, I don't know if the below way is correct to do so.
class Fraction:
def __init__(self, num, denom) -> None:
self.num = self.denom = self.gcd()
if self.denom < 0:
self.denom = abs(self.denom)
self.num = -1*self.num
elif self.denom == 0:
raise ZeroDivisionError("cansnot divide by zero")
def gcd(self):
while self.denom != 0:
self.num,self.denom = self.denom,self.num%self.denom
return abs(self.num)
def get_fraction() -> Fraction:
while True:
num: str = input("Enter the numerator")
denom: str = input("Enter the denominator")
try:
a = int(num)
b = int(denom)
return Fraction(a, b)
except ValueError:
print("Enter valid numerator and denominator")
def compute(f1: Fraction, operator: str, f2: Fraction) -> None:
okay = True
if operator == '+':
result = f1.__add__(f2)
elif operator == '-':
result = f1.__sub__(f2)
elif operator == '*':
result = f1.__mul__(f2)
elif operator == '/':
result = f1.__truediv__(f2)
else:
print(operator, " is an unrecognized operator")
okay = False
if okay == True:
print(f"{f1} {operator} {f2} = {result}")
def main() -> None:
"""Main menu"""
print("Welcome to the Fraction Calculator! ")
while True:
print('Press Q to quit or any other key to start')
z = input("Start or Quit?")
if z == 'Q' or z == 'q':
exit()
else:
f1: Fraction = get_fraction()
operator: str = input("Operation (+, -, *, / , = , < , > , <= ,>= , != ): ")
f2: Fraction = get_fraction()
try:
compute(f1, operator, f2)
except ZeroDivisionError as e:
print(e)
if __name__ == '__main__':
main()
When I execute this I get the below error:
while self.denom != 0:
AttributeError: 'Fraction' object has no attribute 'denom'
I am not sure why this message is thrown.

Related

how to invoke a function in a Python app which has multiple files

I have two or three files in Python for s-expression. But I am not able to invoke the function to calulate the result of s-expression as I am not sure which function to invoke.
I have four files here:
1st file: calc.py
import sys
from parse import *
from expr import *
from calculator import *
def main():
if len(sys.argv)<2:
print('No Input!')
return
expr_list = ParseInput(sys.argv[1]).parse_to_list()
expression = Expression(expr_list)
if not expression.check_validation():
print('Not Valid Input!')
return
calculator = Calculator()
print(calculator.calculate(expression))
if __name__ == '__main__':
main()
2nd file: expr.py
class Expression(object):
def __init__(self, expr_list=None):
self.__expression = expr_list
def get_subexprs(self, expr_list):
res = []
i = 2
while i < len(expr_list)-1:
l = self.count_subexpr_length(expr_list, i)
res.append(expr_list[i:i+l])
i += l
return res
def count_subexpr_length(self, expr_list, i):
j = i+1
if expr_list[i] == '(':
count = 1
while count!= 0 and j<len(expr_list):
if expr_list[j] == ')':
count -= 1
if expr_list[j] == '(':
count += 1
j += 1
return j-i
def check_validation(self):
return self.is_valid(self.__expression)
def is_valid(self, expr_list):
if not expr_list:
return False
if len(expr_list)==1:
return self.is_integer(expr_list)
return self.is_func(expr_list)
def is_func(self, expr_list):
if len(expr_list) < 4:
return False
if expr_list[0] != '(' or expr_list[-1] != ')':
return False
if expr_list[1] not in ['add', 'multiply']:
return False
count = 0
for char in expr_list:
if char == '(':
count += 1
if char == ')':
count -=1
if count <0 :
return False
if count != 0 :
return False
for subexpr in self.get_subexprs(expr_list):
if not self.is_valid(subexpr):
return False
return True
def is_integer(self, expr_list):
return expr_list[0].isdigit()
def get_length(self):
return len(self.__expression)
def get_int(self):
if len(self.__expression) == 1:
return int(self.__expression[0])
def get_operator(self):
if len(self.__expression) > 1 :
return self.__expression[1]
def get_exprlist(self):
return self.__expression
3rd file: parse.py
class ParseInput(object):
def __init__(self, input_string=''):
self.input_string = input_string
def parse_to_list(self):
if self.input_string == '':
print('No Valid Input!')
return None
newString = ''
for char in self.input_string:
if char == '(':
newString += char + ' '
elif char == ')':
newString += ' ' + char
else:
newString += char
return newString.split()
4th file:calculator.py
from expr import *
class Calculator(object):
def __init__(self):
pass
def calculate(self, expression):
return self.calc_expression(expression)
def calc_expression(self, expression):
if not expression:
print('Sorry, you need to load expression!')
return
if expression.get_length() == 1:
return expression.get_int()
operator = expression.get_operator()
if operator == 'add':
return self.calc_add(expression)
if operator == 'multiply':
return self.calc_mul(expression)
def calc_add(self, expression):
base = 0
for subexpr in expression.get_subexprs(expression.get_exprlist()):
base += self.calc_expression(Expression(subexpr))
return base
def calc_mul(self, expression):
base = 1
for subexpr in expression.get_subexprs(expression.get_exprlist()):
base *= self.calc_expression(Expression(subexpr))
return base
The requirement says:
calc.py
Main file to run this calculator engine. Runs the engine in command line, with one valid argument as input.
Example:
$ python calc.py "123"
$ python calc.py "(add 12 12)"
However, I don't see any input expression taking input from the user in calc.py. Also I did the following in Python shell and it gives me the following error.
>>> import calc
>>> calc.py "(add 12 12)"
File "<stdin>", line 1
calc.py "(add 12 12)"
^^^^^^^^^^^^^
SyntaxError: invalid syntax
I want to know which function to invoke and how to invoke that in Python shell?
Update:
When I tried it in the command prompt, it gives me the following error:

I am trying to make a calculator that takes the whole equation and does not use eval()

I am trying to make a calculator that doesn't use eval() and take the whole equation as a string. Also I can't use any libraries, modules, etc. I've managed to make something but I can't figure out how to make it to first do the multiplication and division and then the rest.
It doesn't give me an error but it does this:
4 + 4 = 8
4 + 4 * 4 = 20
4 + 4 * 4 + 4 = 4
Edit: So I found where the problem was, but it still doesn't function right. The problem was that the code doesn't even reach the part where it finds the "*". I'll mark with an arrow where it doesn't reach it.
Here is the code and thanks in advance:
print("Calculator")
# All the numbers
def numbers(num):
return(
num == "0"
or num == "1"
or num == "2"
or num == "3"
or num == "4"
or num == "5"
or num == "6"
or num == "7"
or num == "8"
or num == "9"
)
# All the operators
def operator(oprt):
return(
oprt == "+"
or oprt == "-"
or oprt == "*"
or oprt == "/"
)
# Removes all the spaces
def remove_spaces(string):
string = string.replace(" ", "")
return string
# Does the math between two numbers
def operation(string, num1, num2):
if string == "+":
return num1 + num2
if string == "-":
return num1 - num2
if string == "*":
return num1 * num2
if string == "/":
return num1 / num2
# Tests how long the number is
def test_number(numstr):
n = 0
num = ""
try:
while numbers(numstr[n]):
num += numstr[n]
n += 1
except:
pass
return(int(num), n)
# Solves the equation
def eval_equation(eq):
negative = False
# Removes the spaces
eq = remove_spaces(eq)
while True:
try:
# Checks if the first number is negative
if eq[0] == "-":
negative = True
eq = eq[1:]
# Solves the multiplication first
i = 0
eqTemp = ""
if "*" in eq:
try:
while i < len(eq):
if eq[i] == "+" or eq[i] == "-" or eq[i] == "/":
eqTemp = eqTemp + eq[:i + 1]
print(f"eqTemp = {eqTemp}")
eq = eq[i + 1:]
print(f"eq = {eq}")
elif eq[i] == "*": # <-------this is the problem----
break
print(f"eqTemp = {eqTemp}")
print(f"eq = {eq}")
i += 1
except:
i = 0
# Checks the lenght of the number
number1 = test_number(eq)[0]
# Returns the "-" in the negative number
if negative == True:
number1 = -number1
negative = False
# Removes the first number from the string to continue with the next
endNumber1 = test_number(eq)[1]
eq = eq[endNumber1:]
# Checks for any more numbers
if eq == "":
return number1
# This is the operator sign
op = eq[0]
eq = eq[1:]
# Repeats the same process with the other number
number2 = test_number(eq)[0]
endNumber2 = test_number(eq)[1]
result = operation(op, number1, number2)
# Takes the result and passes it as to the first number along with the rest of the equation
number1 = result
eq = str(number1) + eq[endNumber2:]
eq = eqTemp + eq
except Exception as error:
print(error)
break
return number1
# Main function
if __name__ == "__main__":
while True:
equation = input(": ")
print(eval_equation(equation))
Edit: Sorry, gotta get back to work, wasn't able to figure out your exact problem. I would suggest starting over on the eval_equation function as it's quite messy, and will be prone to bugs if you continue adding to it.
Unrelated to the actual question, here's an example of how you might improve a couple of functions a bit. Note the use of in, the docstrings, as well as a more clear function name.
def is_num(num):
"""Determine if the character is a number."""
return num in '0123456789'
def is_oprt(oprt):
"""Determine if the character is an operator."""
return oprt in '+-*/'
Your test_number function also can be optimised a little by iterating over the string rather than using while with try/except. It's a bit more personal preference but this is how I'd do it:
def get_num(numstr):
"""Gets the number at the start of a string."""
num = []
for i, c in enumerate(numstr):
if not is_num(c):
break
num.append(c)
try:
return int(''.join(num)), i + 1
except ValueError:
return 0, 0
One other syntax suggestion:
number2 = test_number(eq)[0]
endNumber2 = test_number(eq)[1]
Is the same as:
number2, endNumber2 = test_number(eq)
So I fixed it. I'm not sure how... but I fixed it. I just need to figure out how to add variables to the equation now :) . Here is the code and thanks to everybody who gave ideas:
print("Calculator")
# All the numbers
def numbers(num):
return num in {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}
# All the operators
def operator(oprt):
return oprt in {"+", "-", "*", "/"}
# Removes all the spaces
def remove_spaces(string):
string = string.replace(" ", "")
return string
# Does the math between two numbers
def operation(string, num1, num2):
if string == "+":
return num1 + num2
if string == "-":
return num1 - num2
if string == "*":
return num1 * num2
if string == "/":
return int(num1 / num2)
# Tests how long the number is
def test_number(numstr):
n = 0
num = ""
try:
while numbers(numstr[n]):
num += numstr[n]
n += 1
except:
pass
return(int(num), n)
# Solves the equation
def eval_equation(eq):
negative = False
# Removes the spaces
eq = remove_spaces(eq)
while True:
try:
# Checks if the first number is negative
if eq[0] == "-":
negative = True
eq = eq[1:]
# Solves the multiplication first
i = 0
eqTemp = ""
if "*" in eq:
try:
while i < len(eq):
if eq[i] in {"+", "-", "/"}:
eqTemp = eqTemp + eq[:i + 1]
#print(f"eqTemp = {eqTemp}")
eq = eq[i + 1:]
#print(f"eq = {eq}")
pass
if numbers(eq[i]) == True:
pass
if eq[i] == "*":
break
i += 1
except IndexError:
i = 0
# Solves the division first
i = 0
eqTempDiv = ""
if "/" in eq:
try:
while i < len(eq):
if eq[i] in {"+", "-", "*"}:
eqTempDiv = eqTempDiv + eq[:i + 1]
#print(f"eqTemp = {eqTemp}")
eq = eq[i + 1:]
#print(f"eq = {eq}")
pass
if numbers(eq[i]) == True:
pass
if eq[i] == "/":
break
i += 1
except IndexError:
i = 0
# Checks the lenght of the number
number1 = test_number(eq)[0]
# Returns the "-" in the negative number
if negative == True:
number1 = -number1
negative = False
# Removes the first number from the string to continue with the next
endNumber1 = test_number(eq)[1]
eq = eq[endNumber1:]
# Checks for any more numbers
if eqTempDiv == "":
if eqTemp == "":
if eq == "":
return number1
# This is the operator sign
op = eq[0]
eq = eq[1:]
# Repeats the same process with the other number
number2 = test_number(eq)[0]
endNumber2 = test_number(eq)[1]
result = operation(op, number1, number2)
# Takes the result and passes it as to the first number along with the rest of the equation
number1 = result
eq = str(number1) + eq[endNumber2:]
eq = eqTemp + eqTempDiv + eq
#print(f"eqTemp final = {eqTemp}")
#print(f"eq final = {eq}")
except Exception as error:
print(error)
break
return number1
# Main function
if __name__ == "__main__":
while True:
equation = input(": ")
print(eval_equation(equation))

How would I make this more compact and faster? New learner

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)

Recursive Hexadecimal Conversion Python 3

I've made a hexadecimal converter to practice recursion/recursive thinking. I, however, The recurssion doesn't appear to be happening as the functions seems to just output the result of 9 as of current.The code is as follows:
import math
curr=0
def convert(x):
L=len(x)
L-=1
sol=0
if L == 0:
return 0
else:
if x[curr]==["A","a"]:
v=10
elif x[curr]==["B","b"]:
v=11
elif x[curr]==["C","c"]:
v=12
elif x[curr]==["D","d"]:
v=13
elif x[curr]==["E","e"]:
v=14
elif x[curr]==["F","f"]:
v=15
else:
v=int(x[curr])
sol+=((v)*(16**(L-1)))
return sol + convert(x[curr+1])
def main():
print(convert('98A'))
main()
You were setting L = len(x) everytime you call the function. Here is one solution:
import math
def convert(x, L):
c = len(x) - 1
sol=0
if L > c:
return 0
else:
if (x[L]=="A" or x[L]=="a"):
v=10
elif (x[L]=="B" or x[L]=="b"):
v=11
elif (x[L]=="C" or x[L]=="c"):
v=12
elif (x[L]=="D" or x[L]=="d"):
v=13
elif (x[L]=="E" or x[L]=="e"):
v=14
elif (x[L]=="F" or x[L]=="f"):
v=15
else:
v=int(x[L])
sol+=((v)*(16**(c - L)))
print(sol)
return sol + convert(x, L + 1)
def main():
print(convert('98A', 0))
main()
You can use something like this:
class HexMap:
# mapping char to int
d = { hex(n)[2:]:n for n in range(16)}
def convert(x):
s = 0
# use reverse string and sum up - no need for recursion
for i,c in enumerate(x.lower()[::-1]):
s += HexMap.d[c]*16**i
return s
def main():
print(convert('98A'))
main()
Output:
2442
Recursive version:
# class HexMap: see above
def convert(x):
def convert(x,fak):
if not x:
return 0
else:
return HexMap.d[x[-1]]*16**fak + convert(x[:-1],fak+1)
return convert(x.lower(),0)
def main():
print(convert('98A'))
main()
Same output.

Infix to Postfix Converter Python 2.7

I am trying to create a infix to postfix converter in python for a homework assignment, I found multiple ones online that seem simple enough but none of them meet the requirements I need. I have to use the following classes:
class Token(object):
UNKNOWN = 0 # unknown
INT = 4 # integer
MINUS = 5 # minus operator
PLUS = 6 # plus operator
MUL = 7 # multiply operator
DIV = 8 # divide operator
FIRST_OP = 5 # first operator code
def getPrecedence(self):
if self is '(':
return 0
elif self is '+'or '-':
return 1
elif self is '*' or '/':
return 2
else:
return 3
def _init_(self, value):
if type(value) == int:
self._type = Token.INT
else:
self._type = self._makeType(value)
self._value = value
def isOperator(self):
return self._type >= Token.FIRST_OP
def _str_(self):
return str(self._value)
def getType(self):
return self._type
def getValue(self):
return self._value
def _makeType(self, ch):
if ch == '*': return Token.MUL
elif ch == '/': return Token.DIV
elif ch == '+': return Token.PLUS
elif ch == '-': return Token.MINUS
else: return Token.UNKNOWN;
I had to add the getPrecedence(): method, which returns an Integer that represents the precedence level of an operator. I also had to use the following class:
from token import Token
class Scanner(object):
EOE = ';' # end-of-expression
TAB = '\t' # tab
def __init__(self, sourceStr):
self._sourceStr = sourceStr
self._getFirstToken()
def hasNext(self):
return self._currentToken != None
def next(self):
if not self.hasNext():
raise Exception, "There are no more tokens"
temp = self._currentToken
self._getNextToken()
return temp
def _getFirstToken(self):
self._index = 0
self._currentChar = self._sourceStr[0]
self._getNextToken()
def _getNextToken(self):
self._skipWhiteSpace()
if self._currentChar.isdigit():
self._currentToken = Token(self._getInteger())
elif self._currentChar == Scanner.EOE:
self._currentToken = None
else:
self._currentToken = Token(self._currentChar)
self._nextChar()
def _nextChar(self):
if self._index >= len(self._sourceStr) - 1:
self._currentChar = Scanner.EOE
else:
self._index += 1
self._currentChar = self._sourceStr[self._index]
def _skipWhiteSpace(self):
while self._currentChar in (' ', Scanner.TAB):
self._nextChar()
def _getInteger(self):
num = 0
while True:
num = num * 10 + int(self._currentChar)
self._nextChar()
if not self._currentChar.isdigit():
break
return num
I have to write a program that converts a infix expression to a postfix expression. This program should use the Token and Scanner classes (which I have included above). The program should consist of a main function that preforms the inputs and outputs, and a class named IFToPFConverter. The main function receives a input string an creates a scanner with it. The scanner is then passed as a argument to the constructor of the converter object. The converter objects convert method is then run to convert the infix expression. This method returns a list of tokens that represent the postfix string. The main function then displays this string. Here is what I have so far:
from arrayStack import ArrayStack
from token import Token
from scanner import Scanner
class IFToPFConverter(object):
def convert(self):
opStack = Stack()
postFixList = []
while self._scanner.hasNext():
currentToken = self._scanner.next()
if currentToken in '0123456789'
postFixList.append(currentToken)
elif currentToken == '(':
opStack.push(currentToken)
elif currentToken == '*':
opStack.push(currentToken)
elif currentToken == '/':
opStack.push(currentToken)
elif currentToken == '+':
opStack.push(currentToken)
elif currentToken == '-':
opStack.push(currentToken)
elif currentToken == ')':
opStack.push(currentToken)
while not opStack.isEmpty():
def main():
sourceStr = raw_input("Please enter an expression:")
scanner = Scanner(sourceStr)
conversion = IFToConverter.convert(scanner)
return conversion
main()
I don't know where to go from here, I don't even know if what I am trying to do at in my IFToPFConverter class will work. I have seen much simpler infix to postfix converters.

Categories