patternpythonModerate
Password Validation in Python
Viewed 0 times
pythonvalidationpassword
Problem
I coded a python solution for the question below. I am after the fastest solution. Also, I would be grateful if you could point out parts that are not pythonic / inefficient.
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:
P.S: I am not interested in a module / package that can do this faster or more securely. There does not actually exist a website or a username, this is a simple coding exercise.
Also, linked to this post.
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:
- At least 1 letter between [a-z]
- At least 1 number between [0-9]
- At least 1 letter between [A-Z]
- At least 1 character from [$#@]
- Minimum length of transaction password: 6
import warnings
password = 'P@ss1234'
def check_number(s):
''' Check whether the input string is a digit. '''
try:
int(s)
return True
except:
# do not catch error
return False
def check_validity(pw):
''' Return True if input pw is valid, and return False if invalid.'''
special_chars = ['
P.S: I am not interested in a module / package that can do this faster or more securely. There does not actually exist a website or a username, this is a simple coding exercise.
Also, linked to this post.,'#','@']
if isinstance(pw,str): pw=list(pw) # I could have appointed to a diff var name
else: warnings.warn('Password has to be a string object.')
res = False
valid_dict={'small_let':False, 'num':False, 'special_chars':False,
'cap_let':False, 'len':False } # is using a dict efficient?
if len(pw)>= 6: valid_dict['len']=True
for i in pw:
if i.islower(): valid_dict['small_let'] = True
if i in special_chars: valid_dict['special_chars'] = True
if i.isupper(): valid_dict['cap_let'] = True
if not valid_dict['num']: valid_dict['num'] = check_number(i)
if all(valid_dict.values()): res = True
return res
print check_validity(password)P.S: I am not interested in a module / package that can do this faster or more securely. There does not actually exist a website or a username, this is a simple coding exercise.
Also, linked to this post.
Solution
- You shouldn't use bare
excepts, this is as it can prevent things likeKeyboardInterrupt.
That's just bad.
passwordis a better variable name thanpw, at first I was quite confused about what it was.
- You can return early if you know the password is not valid.
This can save you a lot of checks in your program.
- Your program goes through each character and checks if it's one of the four valid groups.
Instead you can check if it shares any items with that set.
If it doesn't it's not valid.
-
You're creating warnings un-neededly, currently, excluding the cast, the functionality is the same if it's a list.
Instead of a warning you should either raise an error, or return.
This is as if I pass
['P', 'a', '$', '2', 1, 2] it probably shouldn't return True, which it might on a different implementation.Instead you can either hard limit your input to strings, or check if the contents of the input are strings. Or both.
In short, just change password to a set, and use
& with the groups it needs to be a part of.This can remove the need to make the function
check_number, and makes the code much more readable:import string
def check_validity(password):
''' Return True if input pw is valid, and return False if invalid.'''
if isinstance(password, str) \
or not all(isinstance(c, str) for c in password):
return False
if len(password) < 6:
return False
password = set(password)
checks = [
set(string.ascii_lowercase),
set(string.ascii_uppercase),
set(string.digits),
{', '#', '@'},
]
for check in checks:
if not check & password:
return False
return True
print check_validity('P@ss1234')Code Snippets
import string
def check_validity(password):
''' Return True if input pw is valid, and return False if invalid.'''
if isinstance(password, str) \
or not all(isinstance(c, str) for c in password):
return False
if len(password) < 6:
return False
password = set(password)
checks = [
set(string.ascii_lowercase),
set(string.ascii_uppercase),
set(string.digits),
{'$', '#', '@'},
]
for check in checks:
if not check & password:
return False
return True
print check_validity('P@ss1234')Context
StackExchange Code Review Q#142880, answer score: 12
Revisions (0)
No revisions yet.