Python input validation with class method check - python

OK, so I've been trying this for about 2 hours now and I can't seem to figure it out. I think I tried almost every possible algorithm combination and it still isn't working. Here it goes:
I'm trying to validate keyboard input in Python based on two condition (ordered by priority):
Check if input is integer
Check if input is vertex (class method for checking if the number given can be found as a key in a dictionary)
Here's the code:
def checkVertex(self, x):
ok = 0
for key in self.__inv:
if key == x:
ok += 1
break
for key in self.__outv:
if key == x:
ok += 1
break
if ok == 2:
return True
return False
def checkInt(number):
if number.isdigit() is False:
return False
return True
def readVertex(msg, graf): <-- this is the issue
"""
msg - string message
graf - Graph() class instance initialised somewhere
invalid_input - string error message
"""
vertex = raw_input(msg)
while checkInt(vertex) is False:
print invalid_input
vertex = raw_input(msg)
if checkInt(vertex) is True:
vertex = int(vertex)
if graf.checkVertex(vertex) is True: <-- this bloody line is not working right
return vertex
else:
continue
return int(vertex)
source = readVertex("Give source vertex (by number): ", G)
dest = readVertex("Give destination vertex (by number): ", G)
cost = int(raw_input("Give cost: "))
print G.addEdge(source, dest, cost)
The problem that I'm getting is that the first condition works, so if I input a letter it will print an error, but if I input a number and that number isn't in the keys of the dictionary it will still return it.
So graf.checkVertex(vertex) always returns True in the above code even though I know for a fact that it works because I've tried the function with the same input in the shell and it returned False.
Let me give you an example, let's say I have this dict:
{0: [], 1: [], 2: [], 3: [], 4: []}
Screen recording of example:

Your validation only runs while checkInt(vertex) is False: - if it is a valid integer the first time, you never check the rest. It's not that graf.checkVertex(vertex) doesn't work; it's never called. Instead, try:
def readVertex(msg, graf, invalid_input):
"""
msg - string message
graf - Graph() class instance initialised somewhere
invalid_input - string error message
"""
while True:
vertex = raw_input(msg)
if checkInt(vertex) and graf.checkVertex(int(vertex)):
return int(vertex)
print invalid_input
or
def readVertex(msg, graf, invalid_input):
"""
msg - string message
graf - Graph() class instance initialised somewhere
invalid_input - string error message
"""
while True:
try:
vertex = int(raw_input(msg))
except ValueError:
print invalid_input
else:
if graf.checkVertex(vertex):
return vertex
print invalid_input

Related

Seeking assistacne with an on online Python course exercise please

I have been doing an online Python course and the final exercise was to check a list of email addresses for invalid addresses.
The code is
def has_invalid_characters(string):
valid = "abcdefghijklmnopqrstuvwxyz0123456789."
# your code here
for i in string:
if i not in valid:
return True
else:
return False
def is_valid(email):
if email.count("#") != 1:
return False
prefix, domain = email.split("#")
if len(prefix) == 0:
return False
if domain.count(".") != 1:
return False
domain_name, extension = domain.split(".")
if len(domain_name) == 0 or len(extension) == 0:
return False
if has_invalid_characters(prefix) == True:
return False
if has_invalid_characters(domain) == True:
return False
else:
return True
emails = [
"test#example.com",
"valid#gmail.com",
"invalid#gmail",
"invalid",
"not an email",
"invalid#email",
"!#/",
"test##example.com",
"test#.com",
"test#site.",
"#example.com",
"an.example#test",
"te#st#example.com",
"test#exam!ple.com"
]
for i in emails:
is_valid(i)
if i == True:
print(i + " is valid")
else:
print(i + " is invalid")
When I run this I am told that the first two email addresses, which should be reported as valid, are invalid, but I cannot figure out why. I have gone over it a few times and cannot see an error in the logic. I have also run it on my laptop and I get the same result.
In the course this code was written in steps and with the last step to change the for loop from simply printing the email addresses to validating them and everything until I modified the for was marked as correct.
I would be grateful if someone could point out the issue with this code to me.
I found the issue. My call to the is_valid() function was not correct.
it should be
for i in emails:
result = is_valid(i)
if result == True:
.....
Sorry for troubling you with this.

Breaking a running user input on auto completion when a certain condition is given

I've got an auto completion function that listen on key. There is an edge case in which the given list to complete from is way too long. So I want to limit the output of possible options and ask the user whether he wants to see the whole amount of possibilities.
Let's say I have this completion function and my_list has about 4000 items.
import readline
my_list = [...]
def completer(text, state):
options = [x for x in my_list if x.startswith(text)]
if state < len(options):
return options[state]
else:
return None
readline.parse_and_bind("tab: complete")
readline.set_completer(completer)
while True:
ans = input("Please select one from the list above: ")
if ans == 'exit':
break
print(ans)
I tried to put the condition inside of def completer() like
def completer(text, state):
options = [x for x in my_list if x.startswith(text)]
if state < len(options):
if len(options) > 50:
question = input(f"Do you want to see all {len(options)} possibilities? ")
if question.lower(0) == "y":
return options[state]
else:
return None
else:
return options[state]
else:
return None
Unfortunately this doesn't work, because there is no way calling the input() function inside the input() function. Do you guys got an idea how to implement this?

python input check function not being called properly

I'm working on a very simple temperature converter in Python (just for practice), and am struggling with some of the UX components. I'd like to have checks in place to continue prompting for variable input when invalid entries are made. My full code is below:
o_temp = ''
def temp_input(o_temp):
o_temp = raw_input('Enter a temperature (round to nearest integer): ')
return o_temp
def temp_input_check(o_temp):
o_temp = list(o_temp)
for i in o_temp:
if i not in '1234567890':
print 'Invalid entry. Please enter only the numerical temperature measurement in integer format.'
temp_input(o_temp)
else:
break
def converter(o_temp):
unit = raw_input('Convert to (F)ahrenheit or (C)elsius? ')
unit = unit.upper()
if unit == 'F' or unit == 'f':
n_temp = (9.0/5.0) * int(o_temp) + 32
print '%d C = %d F' % (o_temp, n_temp)
quit()
elif unit == 'C' or unit == 'c':
n_temp = (5.0/9.0) * (int(o_temp) - 32)
print '%d F = %d C' % (o_temp, n_temp)
quit()
else: #check for valid entry
print 'Invalid entry. Please enter F for Fahrenheit or C for Celsius'
unit_input()
def temp_converter():
#title, call sub-functions
print ''
print 'Temperature Converter'
print ''
temp_input(o_temp)
temp_input_check(o_temp)
converter(o_temp)
temp_converter()
However, when I enter an invalid entry (say, a letter or a combination of letters and numbers) into the o_temp prompt, the code does not seem to recognize that this is invalid and continues with the unit prompt. Am I not correctly returning the variable? What's the issue here? I tried removing the initial o_temp declaration but then I got "NameError: global name 'o_temp' is not defined"
EDIT
I came up with this solution, any further suggestions to refine the code at all?
def converter():
print 'Temperature Converter'
while 1:
temp = raw_input('Starting temperature? ')
try:
temp = float(temp)
except ValueError:
print 'Invalid entry. Please enter only the numerical temperature measurement.'
else:
break
while 1:
unit = raw_input('Convert to Fahrenheit or Celsius? ')
if unit.upper().startswith('F') == True:
print "%f C = %f F" % (temp, temp*9./5+32)
return False
elif unit.upper().startswith('C') == True:
print "%f F = %f C" % (temp, (temp-32)*5./9)
return False
else:
print 'Invalid entry. Please enter F for Fahrenheit or C for Celsius'
converter()
You define some functions, then call temp_coverter(). This function calls temp_input(otemp), sending it an empty string for no reason that I can see, other than the possibility that you're unaware that you can define a function with no parameters. This function then returns a value, which you don't save.
After that, temp_input_check(otemp) is called, which attempts to validate the same empty string. This function's returned value isn't saved, which isn't a big loss, because None isn't a particularly useful value to save.
Then converter(otemp) sends the same old empty string to the actual converter. Mayhem results.
I recommend spending some quality time with the tutorial.
When you're done, the code should look more like this:
def converter():
print 'Temperature Converter'
unit = raw_input('Convert to Fahrenheit or Celsius? ')
while 1:
temp = raw_input('Starting temperature? ')
try:
temp = float(temp)
except ValueError:
print 'Not a valid temperature.'
else:
break
if unit.lower().startswith('f'):
print "%f C = %f F" % (temp, temp*9./5+32)
else:
print "%f F = %f C" % (temp, (temp-32)*5./9)
converter()
Your for loop isn't implemented correctly.
def temp_input_check(o_temp):
o_temp = list(o_temp)
for i in o_temp:
if i not in '1234567890':
print 'Invalid entry. Please enter only the numerical temperature measurement in integer format.'
temp_input(o_temp)
else:
break
You check every character for an invalid entry. If you typed in multiple invalid characters, it'll keep hitting the trigger after you have already determined that the string is invalid!
Also, if your first character is valid, you're telling it to break from the for loop (in your code 1fdsdfdsf would be a valid temperature, because it would skip every character after hitting that else statement and breakout from the loop).
Also, your temp_input doesn't need to accept an argument in the function (you're just gonna return the user's input). You actually want to assign it after you call the function instead of having it as an argument
Also, you're calling temp_input again to get the user input, but not capturing that anywhere with a return - so it's ultimately not doing anything. You should have your function return a True or False, and then catch that on the outside of the checker if you want to have the user try and enter a better temperature:
def temp_input_check(o_temp):
o_temp = list(o_temp)
for i in o_temp:
if i not in '1234567890':
print 'Invalid entry. Please enter only the numerical temperature measurement in integer format.'
return False
else:
pass # nothing is wrong with this character, keep checking
return True # if we hit this line, there were no problem characters
Then, when you call the stuff:
while(1):
o_temp = temp_input()
if temp_input_check(o_temp):
break # this means our o_temp is allllright.
# otherwise, go back to the start of the loop and ask for another temp
converter(o_temp)
because you mentioned 'o_temp' as the function parameter in the end but mentioned it as a empty string at Start. Don't give same names for global & function variables (just to avoid confusion). the function took the o_temp you mentioned above as parameter and neglects the one inside them.
Also the raw_input won't consider the input as string. Try input instead to avoid the sensibility of not using str to correct the loop.
This will do:
def converter():
o_temp = float(raw_input('Enter a temperature (round to nearest integer): '))
for i in str(o_temp):
if i not in ['1','2','3','4','5','6','7','8','9','0','.']:
print 'Invalid entry. Please enter only the numerical temperature measurement in integer format.'
unit = raw_input('Convert to (F)ahrenheit or (C)elsius? ')
if unit in ['f','F']:
n_temp = (9.0/5.0) * float(o_temp) + 32
print '%f C = %f F' % (o_temp, n_temp)
elif unit in ['c','C']:
n_temp = (5.0/9.0) * (float(o_temp) - 32)
print '%f F = %f C' % (o_temp, n_temp)
else: #check for valid entry
print 'Invalid entry. Please enter F for Fahrenheit or C for Celsius'
unit_input()
def temp_converter():
#title, call sub-functions
print ''
print 'Temperature Converter'
print ''
converter()
print temp_converter()

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)

python code problem

i have this code:
class Check(webapp.RequestHandler):
def get(self):
user = users.get_current_user()
be = "SELECT * FROM Benutzer ORDER BY date "
c = db.GqlQuery(be)
for x in c:
if x.benutzer == user:
s=1
break
else:
s=2
if s is 0:
self.redirect('/')
to check whether the user is registered or not.
but it gives me an error:
Traceback (most recent call last):
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/webapp/__init__.py", line 511, in __call__
handler.get(*groups)
File "/Users/zainab_alhaidary/Desktop/الحمد لله/check.py", line 23, in get
if s is 0:
UnboundLocalError: local variable 's' referenced before assignment
what should i do???
Define s before to assign it a value (also, change the test on s):
user = users.get_current_user()
be = "SELECT * FROM Benutzer ORDER BY date "
c = db.GqlQuery(be)
s=0 # <- init s here
for x in c:
if x.benutzer == user:
s=1
break
else:
s=2
if s == 0: # <- change test on s
self.redirect('/')
Why exactly are you loading all users, then looping through them, just to find one? Use a where clause:
be = "SELECT * FROM Benutzer WHERE benutzer=:1"
c = db.GqlQuery(be, user)
user_from_db = c.get()
if user_from_db is not None: # found someone
dostuff()
else:
self.redirect('/')
You're using 's' before you assign something to it. Add an 's = 0' in the appropriate location.
You want to set s to 0 before the for loop starts. If the query returns zero items, your for loop doesn't loop even once, so s is undefined.
Also, you should use if s == 0: instead of if s is 0:. In CPython, they are both equivalent, but you shouldn't rely on the fact. See: the documentation for PyInt_FromLong and "is" operator behaves unexpectedly with integers.
Your problem is that if c is an empty list then the code in the for loop is never run and s never gets set, hence the error:
UnboundLocalError: local variable 's' referenced before assignment
What the error is telling you that you're referencing - i.e. using - s before it has any value - i.e. before a value has been assigned to it.
To fix this you just ensure s always is assigned a value:
s = 0
for x in c:
if x.benutzer == user:
s = 1
break
else:
s = 2
In the case that c is empty the if statement in the loop never gets executed
you should set s=0 before the for loop
I don't know why you are doing this, but if I understand your code correctly, you have s=1 when x.benutzer == user, and s=2 otherwise (shouldn't this be s=0 if you are going to check against 0?).
for x in c:
if x.benutzer == user:
s=1
break
else:
s=2
if s is 0:
self.redirect('/')
Anyway, here's my solution:
if not any(x.benutzer == user for x in c):
self.redirect('/')

Categories