I am trying to write a function in Python that checks a password and returns True or False based on the following criteria:
I have been trying to come up with code for a week now and have tried different variations of the following:
def password_check(str):
list = ['!', '@', '#', '$', '%', '&', '(', ')', '-', '_', '[', ']', '{', '}', ';', ':', '"', '.', '/', '<', '>', '?']
estr = True
if len(str) >= 8:
for i in str:
if i in list:
estr = True
else:
if i.isnumeric():
estr = True
else:
if i.isupper():
estr = True
else:
if i.islower():
estr = True
else:
return False
else:
estr = False
return estr
But the code does not work as intended because if there are, for example, only lower case letters it returns True. So I tried the following:
def password_check(str):
list = ['!', '@', '#', '$', '%', '&', '(', ')', '-', '_', '[', ']', '{', '}', ';', ':', '"', '.', '/', '<', '>', '?']
if any(i.isupper() for i in str) and any(i.islower() for i in str) and any(i.isdigit() for i in str) and len(str) >= 8 and any(i in list for i in str):
estr = True
else:
return False
But it doesn't return False when an invalid character is used (eg ~). The function calls below should return True, True, False, False, False, True, False and False.
print(password_check("tHIs1sag00d.p4ssw0rd."))
print(password_check("3@t7ENZ((T"))
print(password_check("2.shOrt"))
print(password_check("all.l0wer.case"))
print(password_check("inv4l1d CH4R4CTERS~"))
print(password_check('X)ndC@[?/fVkoN/[AkmA0'))
print(password_check(':>&BhEjGNcaSWotpAy@$tJ@j{*W8'))
print(password_check('ZW}VoVH.~VGz,D?()l0'))
I will be most grateful if anyone points me in the right direction.
The issue here is that on the occasion that any rule is true, it returns true. But what you want is for it to check that all rules are true. To do this, we'll need to make four different variables, one for each condition:
def password_check(str):
list = ['!', '@', '#', '$', '%', '&', '(', ')', '-', '_', '[', ']', '{', '}', ';', ':', '"', '.', '/', '<', '>', '?']
hs = False # Has Symbols
hn = False # Has Numbers
hu = False # Has Uppercase
hl = False # Has Lowercase
if len(str) >= 8:
for i in str:
if i in list:
hs = True
elif i.isnumeric():
hn = True
elif i.isupper():
hu = True
elif i.islower():
hl = True
else:
return False
else:
return False
return hs and hn and hu and hl
I tested this and it gave me these results:
True
True
False
False
False
True
False
False
Note the last line there,
return hs and hn and hu and hl
This is basically shorthand for saying this:
if not hs:
return False
if not hn:
return False
if not hu:
return False
if not hl:
return False
return True
By the way, this is a really useful password checker, might come in handy one day!
Without steering you towards a rewrite (which IS a good idea) but only answering your direct question...
You are not checking for "the twist", the case where the password contains an invalid character. To do that, you need to add one more test to your conditional:
and all((i.isupper() or i.islower() or i.isdigit() or i in list) for i in str)
which says that ALL characters in the password must be in one of the valid ranges of characters. If you add this, you get the output you desire.
The full solution, including another minor fix, looks like this then:
def password_check(str):
list = ['!', '@', '#', '$', '%', '&', '(', ')', '-', '_', '[', ']', '{', '}', ';', ':', '"', '.', '/', '<', '>',
'?']
if any(i.isupper() for i in str) and any(i.islower() for i in str) and any(i.isdigit() for i in str) and len(
str) >= 8 and any(i in list for i in str) and all((i.isupper() or i.islower() or i.isdigit() or i in list) for i in str):
return True
else:
return False
and produces:
True
True
False
False
False
True
False
False
You can use this code, it also tells you why the password is incorrect. Simple if and else conditions. But I would prefer if you use RegEx Python
def password_check(password):
SpecialSym = ['!', '@', '#', '$', '%', '&',
'(', ')', '-', '_', '[', ']', '{', '}', ';', ':', '"', '.', '/', '<', '>', '?']
if len(password) < 8:
print('length should be at least 6')
return False
if not any(char.isdigit() for char in password):
print('Password should have at least one numeral')
return False
if not any(char.isupper() for char in password):
print('Password should have at least one uppercase letter')
return False
if not any(char.islower() for char in password):
print('Password should have at least one lowercase letter')
return False
if not any(char in SpecialSym for char in password):
print('Password should have at least one of the symbols $@#')
return False
for i in password:
if not (('0' <= i <= '9') or ('a' <= i.lower() <= 'z')):
# Special Char
if i not in SpecialSym:
return False
return True
Firt off, please don't define a variable called list
(or int
or str
for that matter) as this is a reserved word and a built-in function. Then, you don't need a nested if-block but just a boolean value that gets set to False
if any of the conditions is not met. You can check the conditions independently:
def password_check(p):
print('\nchecking password: ',p)
chlist = ['!', '@', '#', '$', '%', '&', '(', ')', '-', '_', '[', ']', '{', '}', ';', ':', '"', '.', '/', '<', '>', '?']
good_password = True ## Set to true and try to disprove
nums = False
letters = False
special = False
for c in p:
if not (c.isalnum() or c in chlist):
good_password = False
print("Invalid character: "+c)
elif c.isdigit():
nums = True
elif c.isalpha():
letters = True
elif c in chlist:
special = True
if not letters:
good_password = False
print("There are no letters")
if not nums:
good_password = False
print("There are no numbers")
if not special:
good_password = False
print("There are no special characters")
if p == p.lower() or p==p.upper():
good_password = False
print("Please use upper and lower case letters")
if len(p) < 8:
good_password = False
print("Too short")
return good_password
By checking each condition subsequently, you don't have to nest your conditions and can detect the exact problem of the password. You don't need to print them, of course, but this might help in debugging and testing for specific violations.
Try this:
import string
sc = "!@#$%&()-_[]{};:,./<>?"
uc = string.ascii_uppercase
lc = uc.lower()
num = string.digits
def password_checker(password):
if len(password) >= 8:
sn = 0 #numbers of special character
un = 0 #......... uppercase letters
ln = 0 #........ lowercase
dn = 0 #.........digits
for i in password:
if i in uc:
un += 1
elif i in lc:
ln += 1
elif i in num:
dn += 1
elif i in sc and sn == 0:
sn += 1
else:
break
else:
print("Valid Password")
else:
print("Invalid Password")
password_checker(input())
I feel validating each condition step by step is a better approach to avoid confusions. This way we can let the user know what mistake they are committing to correct, rather than to just say if a password is valid or not. Checking the password length and disallowed punctuation will be better ones to start validation.
import re
def password_check(password):
return_value = True
if len(password) < 8:
# print('Password length is less than 8 characters')
return_value = False
punctuation_not_allowed = '[\s+*+=\^`|~]'
if re.search(punctuation_not_allowed, password):
# print(f'Whitespaces or punctuations "*+=\^`|~" is not allowed')
return_value = False
if not any(char.isupper() for char in password) or \
not any(char.islower() for char in password) or \
not any(char.isdigit() for char in password):
# print('Password requires at least one upper case letter, one lower case letter and one digit')
return_value = False
if not re.search(r"""[!@#$%&()\-_\[\]{};':",./<>?]""", password):
# print("""At least special char in "[!@#$%&()-_[]{};':",./<>?]" is required""")
return_value = False
return return_value
Test Cases
print(password_check("tHIs1sag00d.p4ssw0rd."))
print(password_check("3@t7ENZ((T"))
print(password_check("2.shOrt"))
print(password_check("all.l0wer.case"))
print(password_check("inv4l1d CH4R4CTERS~"))
print(password_check('X)ndC@[?/fVkoN/[AkmA0'))
print(password_check(':>&BhEjGNcaSWotpAy@$tJ@j{*W8'))
print(password_check('ZW}VoVH.~VGz,D?()l0'))
Result
True True False False False True False False
I have updated my answer and made it a bit simpler for you to understand. Let me know if this is easier to follow through. The whole program loops through the string only once while checking for everything needed. That way you don't have looping thru many times.
pwd = input('Password :')
#set uppercase, lowercase, digits, special to False
#if password has these, then set to True
ucase = lcase = digit = scase = False
#for loop when applied to a string will pick each char for processing
#this will allow you to check for conditions on the char
for ch in pwd:
#check if char is uppercase, set ucase to True
if ch.isupper(): ucase = True
#check if char is lowercase, set lcase to True
elif ch.islower(): lcase = True
#check if char is a number, set digit to True
elif ch.isdigit(): digit = True
#check if char is special char, set scase to True
#by using in (...), it checks against each item in the list
elif ch in ('!@#$%&()-_[]{};\':",./<>?'): scase = True
#if it is not one of these, then it is not valid password
else:
break
#check if everything is true
if len(pwd) >= 8 and ucase and lcase and digit and scase:
print ('Valid Password')
else:
print ('Invalid Password')
The output for this will be as follows. I ran it multiple times:
Password :thisisnotagoodpassword
Invalid Password
Password :thisis notaG00dPassw0#d
Invalid Password
Password :thisisaG00dPassw0$d
Valid Password
Password :Abcd123$
Valid Password
Password :Abc123$
Invalid Password
How to convert this to a Function:
You can always replace the print statement with a return True or return False statement when you convert this code into a function. Then use the def to create.
def pword(pwd):
#the whole code from #set uppercase... (except first line)
#to the final if statement
#if you want to return True or False, you can use
#return True instead of print ('Valid Password')
To call the function, you can do:
check = pword(input('Password. :'))
That will return the value of True
or False
to check.
Hopefully it was helpful for you to understand the implementation.
I think using regular expression library "re" is the best way of doing this. so simple, so clean.
import re
while True:
p = input('enter a new password: ')
if (len(p) < 6 or len(p)>16):
print('Your password should be between 6-16 characters.')
elif not re.search("[A-Z]", p):
print('Your password should include at least one capital letter.')
elif not re.search('[a-z]', p):
print('Your password should include at least one letter.')
elif not re.search('[0-9]', p):
print('Your password should include at least one number.')
elif not re.search('[@#$%]', p):
print('Your password should include at least one of these signs: @#$%')
else:
print('Your password is valid.')
break
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.