Reputation: 410
I made a validation for entry widget (Tkinter) - accept only: value in range(1, 101) and empty string.
gui part:
entry_hp_treshold_3 = tk.Entry(tab2, width='4', justify='right', validate='key', validatecommand=(validation2, '%P'))
entry_hp_treshold_3.grid(row=2, column=1, padx=0, pady=5)
(1) validation function:
def entry_validation_2(string):
if string == '':
return True
elif int(string) in range(1, 101):
return True
else:
return False
(2) I was trying to write validation function in one line:
def entry_validation_2(string):
return int(string) in range(1, 101) or string == ''
and received: ValueError: invalid literal for int() with base 10: '
(3) I made it work changing the function code to:
def entry_validation_2(string):
return string == '' or int(string) in range(1, 101)
(4) I forgot to add validation if character is a digit, so the first code should be:
def entry_validation_2(string):
if string == '':
return True
elif string.isdigit() and int(string) in range(1, 101):
return True
else:
return False
My question is:
How to write it in just one line as example (3) and avoid the empty string problem? I don't think the example (3) code is good if changing the order causes the error. What is the correct approach?
Upvotes: 0
Views: 108
Reputation: 3934
I don't know away to do it in a one-liner. In the past I've used the exception handling to catch the ValueError and then check the string for non-int cases. The 'Ask for forgiveness not for permission' principle.
def is_valid( string ):
try:
return int(string) in range(1,101)
# Returns True or False if string converts to int
except ValueError:
return string == "" # If string characters not an int is the string empty.
You need to reject all non int possibilities not just accept an empty entry. The string could be formed from any keyboard characters.
Edit: Overnight I came up with a one liner although I'm not sure it's elegant.
import re
def valid( string ):
return re.compile(r'\D').match(string) is None and ( string == "" or int(string) in range(1,101))
Use a regular expression to match any non numeric character. If it does return False otherwise check for an empty string and return True else check for the int conversion in the range.
It would be more efficient to compile the regex outside the validation function.
import re
pattern = re.compile(r'\D')
def valid( string ):
return pattern.match(string) is None and ( string == "" or int(string) in range(1,101))
Does the set up line break the one liner spec?
Upvotes: 1