Reputation: 941
Is there a way in Python to continue checking conditions of an if else statement if one evaluates to true? Here's my code:
status = True
if pass_len(S) == False:
print ('Password must be at least 6 characters long')
status = False
elif pass_upper(S) == False:
print('Password must include upper case letters')
status = False
elif pass_lower(S) == False:
print('Password must include lower case letters')
status = False
elif pass_nums(S) == False:
print('Password must include digits.')
status = False
else:
status = True
return status
For example, if the password doesn't have an uppercase character or numbers, I'd like to print both messages, instead of just "Password must include upper case letters" and it ending right there. I tried getting around this by taking return out of each statement, but it didn't work. Any help is appreciated, thanks.
Upvotes: 2
Views: 11027
Reputation: 54273
Stealing viciously from @JasonS's excellent answer, here's the bit-twiddling approach I mentioned in a comment.
# :: all functions look just like this one! ::
import functools, operator
def pass_len(password, length=6):
try:
if len(password) < length:
return 0b0001
else:
return 0
except Exception as e:
return 0b0001
# pass_upper returns 0b0010 or 0
# pass_lower returns 0b0100 or 0
# pass_nums returns 0b1000 or 0
def password_validate(password):
conditions = [pass_len, pass_upper, pass_lower, pass_nums]
result = functools.reduce(operator.or_, map(lambda x: x(password), conditions))
errors = [message for (bitflag, message) in (
(0b0001, 'Password must be at least 6 characters long'),
(0b0010, 'Password must include upper case letters'),
(0b0100, 'Password must include lower case letters'),
(0b1000, 'Password must include digits.')
) if result & bitflag]
for error in errors:
print(error)
OUTPUT:
>>> password_validate("hunter12")
Password must include upper case letters
>>> password_validate("HUNTER")
Password must include lower case letters
Password must include digits.
>>> password_validate('')
Password must be at least 6 characters long
Password must include upper case letters
Password must include lower case letters
Password must include digits.
You can DRY this off further by doing:
def password_validator(bitflag):
def wrap(f):
def wrapped_f(*args):
return bitflag if f(*args) else 0
return wrapped_f
return wrap
@password_validator(0b0001)
def pass_len(password, length=6):
return len(password) < length
@password_validator(0b0010)
def pass_upper(password):
return password.lower() == password
@password_validator(0b0100)
def pass_lower(password):
return password.upper() == password
@password_validator(0b1000)
def pass_num(password):
return any(num in password for num in '0123456789')
def password_validate(password):
# this function is identical to the one above
Upvotes: 1
Reputation: 13809
An alternate way to do this that is a bit shorter and also gives you a list of which errors triggered is a list comprehension:
errors = [message for (has_error, message) in (
(not pass_len(S), 'Password must be at least 6 characters long'),
(not pass_upper(S), 'Password must include upper case letters'),
(not pass_lower(S), 'Password must include lower case letters'),
(not pass_nums(S), 'Password must include digits.'),
) if has_error]
Upvotes: 6
Reputation: 180550
Don't use elif
, using if
will make sure the the condition is checked. elif
will only be checked when the if
statement evaluates to False
In [40]: foo = 3
In [41]: if foo == 3:
....: print (foo)
....: if foo != 4:
....: print ("checked too")
....:
3
checked too
status = True
sets status to True
already so just return status
no need for an else
Upvotes: 8