Rewriting pre-written code to implement class. (Python) - python

Few days into Python, I wrote this a day ago to get the gist of Python Grammar. While it might not be efficient it works as i intended.
def LongerString():
if len(String1) == len(String2):
return len(String1)
elif len(String1) > len(String2):
return len(String1)
elif len(String1) < len(String2):
return len(String2)
def ShorterString():
if len(String1) == len(String2):
return len(String1)
elif not len(String1) > len(String2):
return len(String1)
elif not len(String1) < len(String2):
return len(String2)
#String1 and 2 from userinput
String1 = input('Input String1\n')
String2 = input('Input String2\n')
#After finishing comparing, evaluates in %
score = 0
for i in range(ShorterString()):
if String1[i] == String2[i]:
score += 1
print(score, "/", LongerString(), "Match", float(score / LongerString()) * 100, "%")
As my progress goes, decided to re-write this code under single class to
get better understanding of how class is used. But looks like I'm missing something. Below is my little attempt.
class CompareString:
def LongerString():
if len(String1) == len(String2):
return len(String1)
elif len(String1) > len(String2):
return len(String1)
elif len(String1) < len(String2):
return len(String2)
def ShorterString():
if len(String1) == len(String2):
return len(String1)
elif not len(String1) > len(String2):
return len(String1)
elif not len(String1) < len(String2):
return len(String2)
def Result():
for i in range(ShorterString()):
if String1[i] == String2[i]:
score += 1
print(score, "/", LongerString(), "Match", float(score / LongerString()) * 100, "%")
String1 = input('Input String1\n')
String2 = input('Input String2\n')
CompareString.Result()
When trying to run latter code i get an error message "line 20, in Result
for i in range(ShorterString()):
NameError: name 'ShorterString' is not defined"

For the immediate problem, you need to call your methods via self - ie self.LongerString() - and they need to accept self as the first argument.
But this isn't really how you use classes. You should write an __init__ method that takes the two strings and stores them as instance attributes, then refer to those throughout.
(Also note, you should use PEP8 style for your variable names.)
class CompareString:
def __init__(self, string1, string2):
self.string1 = string1
self.string2 = string2
def longer_string(self):
if len(self.string1) == len(self.string2):
...
def result(self):
... call self.longer_string() etc ...
compare = CompareString(string1, string2)
print compare.result()
(Also also note, your longer_string method could just be return max(len(self.string1), len(self.string2)), and your shorter_string method similarly.)
(Also also also note, your result method should not iterate over a range, but just over zip(self.string1, self.string2), so you don't even need either of those other methods.)

Related

how can I use multiple else statements?

I want to use a few else statements in my class method:
class Musician :
def __initiate__(self,name, instrument, years_playing, practice_hours):
self.name = name
self.instrument =instrument
self.years_playing = years_playing
self.practice_hours = practice_hours
# self.level = int(self.practice_hours*self.years_playing)
def level(self):
if self.practice_hours <= 1 and self.years_playing <=1:
print (self.name,'is a beginner')
else:
self.practice_hours <=2 and self.years_playing <=2
print (self.name,'is an intermediate')
else:
self.practice_hours <= 3 and self.years_playing <=3
return (self.name, 'is an expert')
player_1 = Musician('Don', 'guitar', 1,3)
player_1.level()
There are many things wrong with your code. The actual question you have seems to be about using elif where you tried to use else; the general structure is
if condition:
something should happen
elif other_codition:
things which should be done in this case
elif third_condition:
other things
else:
unconditionally do this if none of the conditions above were true
where all the branches after the first are optional.
You are mixing print with return, and I'm guessing you meant __init__. Here's an attempt to fix the code.
class Musician:
def __init__(self, name, instrument, years_playing, practice_hours):
self.name = name
self.instrument =instrument
self.years_playing = years_playing
self.practice_hours = practice_hours
# self.level = int(self.practice_hours*self.years_playing)
def level(self):
if self.practice_hours <= 1 and self.years_playing <= 1:
return "beginner"
elif self.practice_hours <= 2 and self.years_playing <= 2:
return "intermediate"
elif self.practice_hours <= 3 and self.years_playing <= 3:
return "expert"
player_1 = Musician('Don', 'guitar', 1, 3)
lvl = player_1.level()
print(f"the level of {player_1.name} is {lvl}")
__init__ is a reserved name for the method which gets invoked when you create a new instance; you can't use a different name and hope for it to be invoked under the shme circumstances.
The level function will still return None if none of its conditions are true, but how to fix that depends on criteria I can't know. Perhaps a better design would be to check for "expert" or "intermediate" and then otherwise always return "beginner" if neither of those are true.
def level(self):
if self.practice_hours > 2 and self.years_playing > 2:
return "expert"
elif self.practice_hours > 1 and self.years_playing > 1:
return "intermediate"
# else
return "beginner"
You can use bisect to achieve the same, without using if
import bisect
def level(self):
level_dict = {0 : 'is a beginner', 1 : 'is an intermediate', 2 : 'is an expert'}
grade_ranges = [(0, 1), (1, 2), (2, 3)]
points, grade = zip(*grade_ranges)
return self.name + level_dict[bisect.bisect(points, self.practice_hours)-1]

How to convert Infix to Postfix using Stack

Here is my code for converting infix to postfix using a previous stack code. The stack code is functional but I don't understand what is wrong with my postix converter code. It is returning "RecursionError: maximum recursion depth exceeded". But I don't think that is the problem. I think it might be the PrecedenceCheck function
def postfix(expr):
if len(expr)<=0 or not isinstance(expr,str):
print("expr error: postfix")
return "error"
expr=expr.strip()
items=Stack()
outputVariable = ""
pos=0
for i in range(len(expr)):
if expr[i] in '+-*/^()':
items.push(expr[pos:i].strip())
items.push(expr[i]) # operator
pos=i+1
items.push(expr[pos:].strip())
elif expr[i] is '1234567890':
outputVariable += i
elif expr[i] is '(':
items.push(expr[i])
elif expr[i] is ')':
while True:
temp = items.pop()
if temp is None or temp == '(':
break
else:
outputVariable += temp
elif expr[i] in '+-*/^' and (items is False or items.peek() is '('):
items.push(expr[i])
elif PrecedenceCheck(expr[i]) is True:
items.push(expr[i])
elif expr[i] in '+-*/^' and PrecedenceCheck(expr[i]) is False:
while True:
items.pop()
if items.isEmpty() is True:
items.push(expr[i])
break
return outputVariable
precedence = {}
precedence['*'] = 3
precedence['/'] = 3
precedence['+'] = 2
precedence['-'] = 2
precedence['('] = 1
precedence['^'] = 1
def PrecedenceCheck(char):
items=Stack()
outputVariable= " "
if char in '1234567890':
return False
elif PrecedenceCheck(char) is True:
while precedence[char] < precedence[items.peek()]:
x = items.pop()
x += outputVariable
items.push(char)
return outputVariable
else:
return 'error message'
Input: ('1 ^ 2')
Expected output: '1.0 2.0 ^'
Actual Output: RecursionError: maximum recursion depth exceeded
if PrecedenceCheck(char) is True: occurs several times, yet PrecedenceCheck can return False or a string, neither of which will be True. Probably better to clean up PrecedenceCheck to always return a bool, or at least change your conditionals to if PrecedenceCheck(char): and cross your fingers that it never returns ''.

python - return returns None

I wrote a function which gets two numbers and an operation (string) and returns the result of the two numbers with the given operation. For example calculate_matehamatical_expression(5,6,'+') should return 11. I divide the the assignment to little functions, but when I call these little function it always returns None. Can someone explain to me why that happens? This is the Code I wrote:
def mathematical_sum(num1,num2):
return num1 + num2
def mathematical_difference(num1,num2):
return num1 - num2
def mathematical_product(num1,num2):
return num1 * num2
def mathematical_division(num1,num2):
if num2 != 0:
return num1 / num2
else:
return None
def operation_error(operation):
if operation != "+" or operation != "-" or operation != "*" or operation != "/":
return None
def calculate_mathematical_expression(num1,num2,operation):
if operation == "+":
mathematical_sum(num1,num2)
elif operation == "-":
mathematical_difference(num1,num2)
elif operation == "*":
mathematical_product(num1,num2)
elif operation == "/":
mathematical_division(num1,num2)
else:
operation_error(operation)
You need to return again inside calculate_mathematical_expression, e.g.:
def calculate_mathematical_expression(num1,num2,operation):
if operation == "+":
return mathematical_sum(num1,num2)
The return in mathematical_sum doesn't affect the function it's being called from.
Your calculate_mathematical_expression function is not returning anything. Try following code:
def calculate_mathematical_expression(num1,num2,operation):
if operation == "+":
return mathematical_sum(num1,num2)
elif operation == "-":
return mathematical_difference(num1,num2)
elif operation == "*":
return mathematical_product(num1,num2)
elif operation == "/":
return mathematical_division(num1,num2)
else:
return operation_error(operation)
You need to return
When you return from a function, it only returns to the function that called it. So when you return in mathematical_sum(), the value is returned to calculate_mathematical_expression() & you need to return again from this function, like this:
if operation == "+":
return mathematical_sum(num1,num2)
elif operation == "-":
return mathematical_difference(num1,num2)
elif operation == "*":
return mathematical_product(num1,num2)
elif operation == "/":
return mathematical_division(num1,num2)
else:
return operation_error(operation)
...otherwise calculate_mathematical_expression() returns None.
operation_error() does not work
Use and instead of or. Otherwise your condition will always be True
Return a boolean, not None. Here, your function always return None
Example:
def operation_error(operation):
return operation != "+" and operation != "-" and operation != "*" and operation != "/"
You don't need operation_error()
Since you have a condition for each operator, you don't need the operation_error() function, you can directly do this:
else:
return None
...or even remove the else statement and let calculate_mathematical_expression() automatically return None when reaching its end.

Python invalid literal for int() with base 10: '+'

So first, the assignment given was to make the function "compute" solves it and returns the value. If the given sting is not a valid equation, returns "None"
def compute(side):
val=int(side[0])
lastop=0
for i in range(1,len(side)):
if side[i].isdigit():
if lastop=='+':
val+=int(side[i])
elif lastop=='-':
val-=int(side[i])
elif lastop=='x':
val*=int(side[i])
elif lastop=='/':
val/=int(side[i])
else:
lastop=side[i]
return val
So at this point the value would be returned. But if the function is run for ("22-11x4"), it gives 0 not 44. I've turned them into integers and why would they still give me the wrong value?
def evaluate():
val=int(side[0])
lastop=0
for i in range(1,len(side)):
if side[i].true():
print('Congrats')
elif side[i].false():
print('Try again')
And when it gets to this evaluate function, it gives the error of "invalid literal for int() with base 10: '+'" and I am not too sure what this means and how to solve.
def solve():
pass
This function "solve" I was going to get to later after I have fixed the problems in the functions before.
def main():
print("22-11x4 =", compute("22-11x4"),"(expect 44)")
print("+11x4 =", compute("+11x4"),"(expect None)")
print("22-11x4 ?= 7x5+9", evaluate("22-11x4=7x5+9"),"(expect True)")
print("solving 288/24x6=18x13x8 :", solve("288/24x6=18x13x8"))
main()
The compute function you wrote does operation by digit, also you forgot to do one, last operation after for was finished:
2 - 1 - 1 x 4 = 0
this why you got this return from the function
Here is the correct function
def compute(side):
val = 0
buf = 0
lastop = '+'
for i in range(0, len(side)):
if side[i].isdigit():
buf = buf * 10 + int(side[i])
else:
val = op(val, buf, lastop)
lastop = side[i]
buf = 0
val = op(val, buf, lastop)
return val
def op(val, buf, lastop):
if lastop == '+':
val += buf
elif lastop == '-':
val -= buf
elif lastop == 'x':
val *= buf
elif lastop == '/':
val /= buf
return val
Also in your testing string:
print("+11x4 =", compute("+11x4"),"(expect None)")
why do you expect None? it should be 44?
PS. this function could be improved yet, but I had no time to do it. anyway it works.

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