Jose Magana
Jose Magana

Reputation: 941

Check every condition in Python if else even if one evaluates to true

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

Answers (3)

Adam Smith
Adam Smith

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

Jason S
Jason S

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

Padraic Cunningham
Padraic Cunningham

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

Related Questions