Accessing a variable inside of a function, from another function - python

I have function AB which has 1 parameter, and AB has a bunch of loops and I have a counter which keeps track of how much it loops. It (must) returns an either True or False answer.
I have a second function called AC which calls upon 2 instances of AB with different things for the parameters and compares them like so
if (AB(option1) == True and AB(option2) == False):
result = "Option1 Wins"
elif (AB(option1) == False and AB(option2) == True):
result = "Option2 Wins"
if (AB(option1) == True and AB(option2) == True):
result = ??
however if both cases are 'True', I need to know which case reached 'True' first, so this means I would need to know how many times it loops (i need to know the value of the counter variable)
How can I access the variable?
I was thinking of making a helper function to access it but I'm not sure if that's possible/how to do that

You can return more than one value from a function in python:
def AB(param):
return True, 1
val = AB(1) # it will be (True,1), so it's a set
val, val1 = AB(2) # val = True, val1 = 1
So in your code you should check AB(param)[0] to check True, if you want to keep only one return value (you should get them in different variables).
But your code is wrong, since you are calling AB() each time you are checking the output, which will execute all the loops and, eventually, could bring an unexpected response for the same input. You should get the output from AB() for each param before, and then check them in your if block.

Zero evaluates to False and non-zero evaluates to True:
If AB fails it returns 0 otherwise it returns the amount of loops:
def AB(param):
if failed:
return 0
else:
return counter
Usage:
if AB(option1) and not AB(option2):
result = "Option1 Wins"
elif not AB(option1) and AB(option2):
result = "Option2 Wins"
elif AB(option1) < AB(option2):
result = "Option1 Wins"
else:
result = "Option2 Wins"

OOP solution: Create a class with this methods as member function and the counter variable as a member variable. Now you can check that value from anywhere for any object of that class.
Also in your code, no need to invoke AB multiple times.
o1 = AB(option1)
o2 = AB(option2)
if o1 and not o2:
result = "Option1 Wins"
elif not o1 and o2):
result = "Option2 Wins"
elif o1 and o2:
result = ??
An object oriented solution might look like following (code not tested)
class solver(object, option):
reached = 0
option = option
status = False
def AB(self):
# implementation. use self.option and update self.reached and self.status
opt1 = solver(option1)
opt2 = solver(option2)
o1 = opt1.AB()
o2 = opt2.AB()
if o1.status and not o2.status:
result = "Option1 Wins"
elif not o1.status and o2.status):
result = "Option2 Wins"
elif o1 and o2:
if o1.reached < o2.reached:
# o1 reached first

You can use global variables to store values of the counters. See http://www.diveintopython.net/html_processing/locals_and_globals.html for more details.

Related

Python: How to determine if a String can be converted to an integer with no issues

I am writing a program that has multiple functions to execute, and the user selects which one runs by inputting a number. I also want the user to be able to let the user cancel the request by typing "cancel".
Right now this is my code:
func = input("Requested Operation: ")
if func == 'Cancel' or func == 'cancel':
break
elif func == '' or func == ' ' or func == '0':
func = 0
elif type(int(func)) is int:
func = int(func)
else:
fail = True
Context: Function 0 displays a list of the available items to choose from, so I want whitespace or 0 to work as displaying the project list. If the user types "Cancel" or "cancel" it will end the program.
The problem I am having is line 6 (the 2nd elif). My goal is to set the fail variable to True if the user inputs a string that isn't a cancel command, so the code breaks right there and starts over. The problem is, how do I preemptively check if a string can be converted to an integer in the first place? My current iteration returns the error invalid literal for int() with base 10: 'asdg' (asdg being the random nonsense that should make fail = True).
Also, I understand this method is probably super inefficient. Essentially, I want the conditional to be "if func is cancel, break. If func is whitespace or '0', then it equals 0. If func is some non-0 integer, convert the string to an integer and continue. Otherwise, set fail to True and break."
My knowledge of python is minimal so I would very much appreciate a full explanation or link to documentation so I can learn as much as possible.
Thanks in advance :)
Edit: This is the entire module
import projects.dice_app as dice_app
import projects.text_to_math as text_to_math
def main():
f = open("readme_files/index.txt")
p = open("readme_files/projects.txt")
print(f.read())
func = 0
while True:
fail = False
func = input("Requested Operation: ")
if func == 'Cancel' or func == 'cancel':
break
elif func == '' or func == ' ' or func == '0':
func = 0
elif type(int(func)) is int:
func = int(func)
else:
fail = True
break
if func == 0:
p = open("readme_files/projects.txt")
print(p.read())
elif func == 1:
dice_app.dice_func()
elif func == 2:
text_to_math.ttm_func()
else:
print("Invalid operation. Please try again.")
if __name__ == "__main__":
fail = False
main()
while fail == True:
main()
elif func.isnumeric():
func = int(func)
try :
func = int(func)
except ValueError:
print('not a number')
This should work

binary search for list in python

My code for binary search function in a list returns true for a value in the list, but returns None (instead of false) for values not in the list.
Can someone please explain me what I'm doing wrong?
The program is:
def searchlist(x,alist):
end=int(len(alist)-1)
mid=int(len(alist)/2)
while len(alist)>2:
if x==alist[mid] or x==alist[0] or x==alist[end] :
return("true")
break
elif x>alist[mid]:
alist=alist[mid:]
mid=int(len(alist)/2)
end=int(len(alist)-1)
elif x<alist[mid]:
alist=alist[:mid]
mid=int(len(alist)/2)
end=int(len(alist)-1)
else:
return("false")
aList=[2,3,5,7,9,12,14,23,34,45,67,89,101]
xnum=int(input("enter a number:"))
searchlist(xnum,aList)
print(searchlist(xnum,aList))
You get None when your function does not return a value. This happens because the while loop terminates without going into the "else" branch.
A better practice would be to return True (not the string, but the Boolean value) when you find the value in the list, and return False after the loop.
Your while loop cannot catch the else statement. you don't need that else. try this :
def searchlist(x,alist):
end=int(len(alist)-1)
mid=int(len(alist)/2)
result = False
while len(alist)>2:
if x==alist[mid] or x==alist[0] or x==alist[end] :
result = True
elif x>alist[mid]:
alist=alist[mid:]
mid=int(len(alist)/2)
end=int(len(alist)-1)
elif x<alist[mid]:
alist=alist[:mid]
mid=int(len(alist)/2)
end=int(len(alist)-1)
return result
aList=[2,3,5,7,5,67,89,101]
xnum=int(input("enter a number:"))
print(searchlist(xnum,aList))

How to make it run through my whole range?

def isprimelike(n):
for a in range(2,n-1):
if pow(a,n,n) == a%n:
return True
else:
return False
When I check n for a given value it just check 2, then decides if it is true or false and doesn't check the rest of the range. Not sure how to make it check the rest of the range.
That's because you're using a return inside the if-else block. You might want to change the return statement by a print one indicating if it is a prime number or not.
If you want it to return True if all are prime-like or False if at least one is not, then do the following:
def isprimelike(n):
for a in range(2,n-1):
if pow(a,n,n) != a%n:
print('One element is false')
return False
return True
The print statement is just to show something, but it's not relevant.
I would try making a list and allow your for loop to append the results of the range into the list then return the list as a whole so you can have access to all the results.
edit: Complely missed the point of your question. Here's the edit.
import sys
def isprimelike(n):
resultlist = []
for a in range(2,int(n)-1):
if pow(a,int(n),int(n)) == a%int(n):
result.append(True)
else:
result.append(False)
return resultlist
n = sys.argv[1]
resultlist = isprimelike(n)
if True in resultlist:
if False in resultlist:
print('List contains both True and False')
sys.exit(1)
else:
print('List is all True')
sys.exit(1)
if False in resultlist:
if True in resultlist:
print('List contains both True and False')
else:
print('List is all False')

How to simplify my elif code in python

I am viswa. I prepared a simple code using elif command.
I will share the code and condition... it is working. but I am looking for simplified program. if anything available for the same result
inputs names are= 'AEX_ABC','AEX_XXX','AEX_YYY','CAI_XXX','CAI_YYY'....etc.,
output should be AEX_1,AEX_2,AEX_3,CAI_1,CAI_2,....
program:
name=(<user input>)
AEX,CAI,CAR,CCA,CEL,CLM,CRE,ECH,FAV,FRE,GMP,INS,ROU,TAR,TAV,UAV,VEH,ERROR=0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
name=part._name.split('_')
if name[0]=='AEX':
AEX+=1
i=AEX
elif name[0]=='CAI':
CAI+=1
i=CAI
elif name[0]=='CAR':
CAR+=1
i=CAR
elif name[0]=='CCA':
CAR+=1
i=CCA
elif name[0]=='CEL':
CEL+=1
i=CEL
elif name[0]=='CLM':
CLM+=1
i=CLM
elif name[0]=='CRE':
CRE+=1
i=CRE
elif name[0]=='ECH':
ECH+=1
i=ECH
elif name[0]=='FAV':
FAV+=1
i=FAV
elif name[0]=='FRE':
FRE+=1
i=FRE
elif name[0]=='GMP':
GMP+=1
i=GMP
elif name[0]=='INS':
INS+=1
i=INS
elif name[0]=='ROU':
ROU+=1
i=ROU
elif name[0]=='TAR':
TAR+=1
i=TAR
elif name[0]=='TAV':
TAV+=1
i=TAV
elif name[0]=='UAV':
UAV+=1
i=UAV
elif name[0]=='VEH':
VEH+=1
i=VEH
else:
ERROR+=1
i='error'+str(ERROR)
output=name[0]+i
print(output)
You can replace this with a dictionary lookup.
stock_indices={<all stock indices:0>}
error=0
try:
stock_indices[input[0]]+=1
except KeyError:
error+=1
As Jesse Bakker says, this is a job for a dictionary. Whenever you find yourself creating a whole bunch of variable names to track a group of related items you should probably be using a dictionary instead. You can use a dict literal to initialize the dictionary, but when all of the items have the same initial value it's convenient to use the dict.fromkeys class method, as shown below.
To keep the code lines short I've split the keys string into two strings: Python will automatically join adjacent string literals, but we need to wrap the expression with parentheses so that the parser knows that it continues over more than one line.
keys = ('AEX,CAI,CAR,CCA,CEL,CLM,CRE,ECH,FAV,FRE,'
'GMP,INS,ROU,TAR,TAV,UAV,VEH,ERROR'.split(','))
stock_indices = dict.fromkeys(keys, 0)
def update_stock(name):
key = name.partition('_')[0]
if key not in stock_indices:
key = 'ERROR'
val = stock_indices[key] + 1
stock_indices[key] = val
return key, val
# Test
test = (
'AEX_ABC',
'AEX_XXX',
'AEX_YYY',
'BAD_ZZZ',
'CAI_XXX',
'CAI_YYY',
)
for name in test:
key, val = update_stock(name)
print('{0}_{1}'.format(key, val))
output
AEX_1
AEX_2
AEX_3
ERROR_1
CAI_1
CAI_2

Understanding True/False evaluations in the context of Python dictionaries

I am working through the EdEx 6.00.2x course online and am struggling with one portion of my code:
newResistances = copy.deepcopy(self.resistances)
for drugs in self.resistances:
resistancePicker = random.random()
if self.resistances[drugs] == True:
if resistancePicker < self.mutProb:
print self.mutProb
newResistances[drugs] = False
elif self.resistances[drugs] == False:
if resistancePicker < self.mutProb:
print self.mutProb
newResistances[drugs] = True
print newResistances
return ResistantVirus(self.maxBirthProb, self.clearProb, newResistances, self.mutProb)
self.resistances is a dictionary containing drug name keys, and True or False values {'a':True,'b':True}. My problem is that only the first element of the dictionary seems to be evaluated and changed in the newResistances dictionary. Please let me know if this question is too vague/needs more context.
This is because your return is the wrong location. If you move it to line up with the for, you will see the code iterate through all keys.
I have also updated the code to remove constructs like if predicate==True since you could just do if predicate: instead.
Here's how the code should look:
for drugs in self.resistances:
resistancePicker = random.random()
if self.resistances[drugs]:
if resistancePicker < self.mutProb:
print self.mutProb
newResistances[drugs] = False
elif not self.resistances[drugs]: # or else:
if resistancePicker < self.mutProb:
print self.mutProb
newResistances[drugs] = True
print newResistances
return ResistantVirus(self.maxBirthProb, self.clearProb, newResistances, self.mutProb)

Categories