ah-morris
ah-morris

Reputation: 21

Writing a password validity check function

I have recently started learning Python and begun working through scenarios when I came across this one:

Question: A website requires the users to input username and password to register. Write a program to check the validity of password input by users. Following are the criteria for checking the password: 1. At least 1 letter between [a-z] 2. At least 1 number between [0-9] 1. At least 1 letter between [A-Z] 3. At least 1 character from [$#@] 4. Minimum length of transaction password: 6 5. Maximum length of transaction password: 12 Your program should accept a sequence of comma separated passwords and will check them according to the above criteria. Passwords that match the criteria are to be printed, each separated by a comma. Example If the following passwords are given as input to the program: ABd1234@1,a F1#,2w3E,2We3345 Then, the output of the program should be: ABd1234@1*

My approach to the problem was the following code:

'''

def validity_check(pword):
return \
    (any(i.islower() for i in pword)) and \
    (any(i.isnumeric() for i in pword)) and \
    (any(i.isupper() for i in pword)) and \
    (any((i == "$" or i == "#" or i == "@") for i in pword)) and \
    (6 <= len(pword) < 13)

raw_input = input("Please enter a series of passwords to check, separated by a comma: ")
raw_list = raw_input.split(",")
valid_pwords = []
for i in raw_list:
    if validity_check(i) == True:
        valid_pwords.append(i)
print(",".join(valid_pwords))

'''

My solution seems to work, but my question is regarding readability. Since beginning these Python problems I've become a bit obsessed with having as few lines of code as possible. Could the program be shorter? I chose to use a single function with ternary operators, does this compromise readability?

Also as I'm new to Python, any help and criticism with the program in general is very welcome!

Upvotes: 0

Views: 707

Answers (2)

Dilumika Nawodya
Dilumika Nawodya

Reputation: 93

You can use regular expression to solve this and i think it will help you,

import re

pattern = r'^([^a-z]*|[^A-Z]*|[^0-9]*|[^#$@]*)$'

wordlist = list(map(str,input("Please enter a series of passwords to check, separated by a comma: ").split(',')))
for i in wordlist:
    if not(re.match(pattern,i)) and (5<len(i) and len(i)<13):
       print(i)

Note : This regex pattern matches a password which does not belong to this category and within if statement it returns true to valid passwords.

Thank you !

Upvotes: 1

chepner
chepner

Reputation: 532458

PEP 8 has some specific suggestions for formatting your validity_check function:

  • Prefer implicit line continuation inside parentheses to explicit line continuations using a backslash
  • Put binary operators at the beginning of a continued line.

Further, since you have a bunch of Boolean values anded together, perform the cheapest ones first. Especially here, you want to reject a password with the wrong length before you go to the trouble of iterating over it multiple times to verify the other conditions.

Finally, prefer a containment check to multiple equality checks, and drop the redundant parentheses.

def validity_check(pword):

    return (6 <= len(pword) < 13
            and any(i.islower() for i in pword)
            and any(i.isnumeric() for i in pword)
            and any(i.isupper() for i in pword)
            and any(i in "$#@" for i in pword))

Anything shorter would probably do more to obscure what you are doing than to describe it.

Upvotes: 0

Related Questions