2

I have the following code to test a password for strength:

import string
def golf(password):
    if len(password) >= 10:
        if any(char.isdigit() for char in password):
            if any(string.punctuation for char in password):
                if any(char.isalpha() for char in password):
                    if any(char.isupper() for char in password):
                        if any(char.islower() for char in password):
                            return True
    return False

I know it can be done better! It needs to test for the following ...

The password will be considered strong enough if it has at least 10 characters contains at least one digit contains at least one uppercase letter contains at least one lowercase letter. The password may only contain ASCII Latin letters or digits, but no punctuation symbols.

EDIT

OK for anyone else i got it down to the following with regex.

import re
def golf(password):
    return re.match( r'^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.{10,30}).+$', password)

Apparently it can still be shorter...

3 Answers3

3

Actually, you're quite close. Yes, you have a variety of conditions to check; the rules are that complication. Note that you don't have to check for alpha: the checks for islower and isupper cover that. You can make this just a little easier to handle by putting the rules into a single expression:

import string
def golf(password):
    return \
        len(password) >= 10                              and \
        any(char.isdigit() for char in password)         and \
        not any(string.punctuation for char in password) and \
        any(char.isupper() for char in password)         and \
        any(char.islower() for char in password)

Note that you're evaluating a Boolean expression: just return that value. There's no need to say

if <expr>:
    return True
else:
    return False

You already have the value in hand; just return it.

Prune
  • 76,765
  • 14
  • 60
  • 81
0

That's one long string of if statements XD. You should just use some and statements.

if len(password) >= 10 and any(char.isdigit() for char in password)...:
    return True
else:
    return False

The else statement is not necessary, as you know, but it makes the code more readable.

Matthew
  • 472
  • 2
  • 5
  • 12
  • Thanks for that , Yes it is shortened if you use and statements but harder to read also , i believe it can be readable and shorter. – allen simpson Jul 19 '17 at 00:55
0

The more optimal way would be to do your character checking all in one loop.

import string
def golf(password):
    if len(password) < 10:
      return False

    saw_digit = saw_upper = saw_lower = False
    no_punct = all_alnum = True

    for char in password:
      saw_digit = saw_digit or char.isdigit()
      saw_upper = saw_upper or char.isupper()
      saw_lower = saw_lower or char.islower()
      no_punct = no_punct and (char not in string.punctuation)
      all_alnum = all_alnum and char.isalnum()

    values = [saw_digit, saw_lower, saw_upper, no_punct, all_alnum]
    # print(values)
    return all(values)
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245