I am supposed to write a script with the following criteria:
Write a function called validatePassword that takes a password string as a parameter and returns true or false. The function should only return true if:
The password is at least 8 characters
The password contains at least one number
The password contains at least one upper case letter. Hint: use the isupper() string function.
The password contains a symbol one of the symbols !##$%^&*()+=
I have this so far:
def validatePassword(pswd):
if len(pswd)> 8:
return True
else:
return False
for char in pswd:
if char in '01234567890':
return True
else:
return False
for char in pswd:
if char in '!##$%^&*()_+=':
return True
else:
return False
for char in pswd:
if char.isupper and char .islower:
return True
else:
return False
return True
while False:
print("There was an error with your password")
print (validatePassword(Herseuclds))
I know that print (validatePassword(Herseuclds)) has a syntax error because I am missing the variable but I just don't get how to do this.
def validatePassword(pswd):
if len(pswd) < 8:
return False
number_in_password = False
for char in pswd:
if char in '012356789':
number_in_password = True
if not number_in_password:
return False
symbol_in_password = False
for char in pswd:
if char in '!##$%^&*()_+=':
symbol_in_password = True
if not symbol_in_password:
return False
uppercase_in_password = False
for char in pswd:
if char.isupper():
uppercase_in_password = True
if not uppercase_in_password:
return False
#this only happens if nothing above has disqualified the password
return True
print (validatePassword("herseuc"))
print (validatePassword("herseuclds"))
print (validatePassword("herseuclds!"))
print (validatePassword("herseuclds!123"))
print (validatePassword("herseuclds!123A"))
The main issue with your code is in the last line.
print (validatePassword(Herseuclds))
Right now, the interpreter thinks Herseuclds is a variable, and not a string. If Herseuclds is the password, and not a variable describing the password, then you need quotes around it to make it a string literal.
print (validatePassword("Herseuclds"))
You obviously haven't defined a variable called Herseuclds anywhere in your program, but the program thinks Herseuclds is a variable and not a string, so it throws the error.
Best of luck, and happy coding!
First issue is that you are passing an undeclared variable to your function. See silentphoenix's answer for details.
Secondly, your program only check to see if AT LEAST ONE condition is met, not all.
If a password is 8 characters long, it will return true even if the password doesn't satisfy the other requirements.
I am not going to write your code for you, but I can pseudocode the issue:
def validatePassword(pswd):
if len(pswd) < 8:
return False
# if there isn't a number:
return False
# if there isn't a symbol:
return False
# if there isn't an upper and lowercase:
return False
return True
while True:
print("There was an error with your password")
print (validatePassword("Herseuclds"))
sidenote: watch your indentation :)
Since you can use is.upper() you can also utilize is.digit() to check for numbers instead of having to write down actual digits.
Another thing to speed it up, since they all have to be done at the same time, you can check if the password validates those requirements in one line with any()
def validatePassword(pswd):
l = []
if len(pswd)> 8:
for char in pswd:
l.append(char)
if any(l for x in l if x.isdigit()) and any(l for x in l if x.isupper()) and any(l for x in l if x in '!##$%^&*()_+='):
print('Success')
else:
print('Try again')
while True:
a = input('What is your password?')
validatePassword(a)
At the beginning there's an minimum check to see if the lengeth is greater than 8. If it is, the word gets broken up into a list. This allows any() to be used and checked against the remainding requirements.
def valid_password(password):
return (
# The password is at least 8 characters
len(password) >= 8 and
# The password contains at least one number
any(c in "0123456789" for c in password) and
# The password contains at least one upper case letter
any(c.isupper() for c in password) and
# The password contains a symbol one of the symbols !##$%^&*()+=
any(c in "!##$%^&*()+=" for c in password))
Example:
from getpass import getpass
while not valid_password(getpass('Enter password: ')):
print('invalid password. Try again')
Related
Is it possible to assign a variable to an return result of an function ?
First I want to acquire the website from email like for e.g xxxxx#hotmail.com will return only hotmail.com. Then if that website is equal to 'hotmail.com' return 'Yes' if not equal return 'No'.
def mail(var):
x = return var.split('#')[1]
if x == 'hotmail.com':
return 'Yes'
else:
return 'No'
I know it's not the right code but I hope You get the idea. Thanks for your help !
I think what you want is this:
def mail(var):
return 'Yes' if var.split('#')[1] == 'hotmail.com' else 'No'
x = mail('foo#hotmail.com')
print(x)
Note:
If var does not contain '#' this will fail with IndexError
You have to remove your first return, beacause then your function immediately exits, then it works:
def mail(var):
x = var.split('#')[1]
if x == 'hotmail.com':
return 'Yes'
else:
return 'No'
print(mail('user#hotmail.com'))
print(mail('user#gmail.com'))
Output:
Yes
No
I suggest to validate the email in parameter to avoid exception by checking if it contains '#' in argument and checking for dot ('.') within index of '#' to the last char, if it's invalid then return 'is not valid email'. If it's a valid email then assign the value of variable x by indicing from next index of '#' (same result as split). And the last, check if x is fit to the condition that you want (in this example: 'hotmail.com')
def mail(var):
if '#' in var and '.' in var[var.index('#'):]:
x = var[var.index('#')+1:]
print(x)
return 'Yes' if x == 'hotmail.com' else 'No'
else:
return f'{var} is not valid email'
print(mail('xxxxx#gmailjp'))
print(mail('xxxxxgmail.com'))
print(mail('xxxxxgmailnl'))
print(mail('xxxxx#gmail.us'))
print(mail('xxxxx#hotmail.com'))
# xxxxx#gmailjp is not valid email
# xxxxxgmail.com is not valid email
# xxxxxgmailnl is not valid email
# gmail.us
# No
# hotmail.com
# Yes
But I prefer this:
def mail(var):
return 'Yes' if 'hotmail.com' in var else 'No'
print(mail('xxxxx#gmail.us'))
print(mail('xxxxx#hotmail.com'))
# No
# Yes
for c in password:
if not any(c in password for c in symbols):
return False
if not any(c.isdigit() for c in password):
return False
if not any(c.islower() for c in password):
return False
if not any(c.isupper() for c in password):
return False
return
print(password)
f = open("demofile2.txt", "a")
f.write(password + "\n")
f.close()
You want to avoid doing extra work when verifying that your password satisfies all requirements. In my example, I've looked at each character only once and am performing the required checks every time I look at a different character.
In the example you provided, you're actually verifying that every character meets your requirements for every character in the password O(N*N) - this is not recommended.
Lastly, make sure you understand what the password requirements are. It seems like your logic is incorrect when trying to verify that a character is both lowercase and uppercase simultaneously.
edit: The author clarified in comments that in order for a password to be valid, that password must have at least:
one symbol
one digit
one lowercase character
one uppercase character
has_symbol = False
has_digit = False
has_lower = False
has_upper = False
for c in password:
if has_symbol and has_digit and has_lower and has_upper:
break
elif c in symbols:
has_symbol = True
elif c.isdigit():
has_digit = True
elif c.islower():
has_lower = True
elif c.isupper():
has_upper = True
if has_symbol and has_digit and has_lower and has_upper:
print(password)
f = open("demofile2.txt", "a")
f.write(password + "\n")
f.close()
else:
return False
you should take care about time complexity by avoiding unnecessary
loops.
this will help you:
from string import punctuation
def check_pass(password):
return all([any(filter(str.islower, password)),
any(filter(str.isupper, password)),
any(filter(str.isdigit, password)),
any(filter(lambda x: x in punctuation, password))
]
)
def save_password(password):
if check_pass(password):
with open("demofile2.txt", "a") as f:
f.write(password)
print(password)
else:
print('Not Accepted!')
# Test
save_password('1#cA')
I have two files and I want to store in Username.txt, but my function just drops me a "None".
def username_input(user):
user_len = int(len(user))
while user_len > 12 or not (user.isalnum()):
print("Error: the username must be an alphanumeric value \nand have as maximum 12 characters")
user = input("Type a valid username: ")
user_len = int(len(user))
if user_len <= 12 and user.isalnum():
return user
with open("Username.txt", "a") as usr_txt:
usr = username_input(user = input("Type a username: "))
usr_txt.write(usr)
In python, no return or return means return None. If never enter the while user_len > 12 or not (user.isalnum()):, it will reach end and no return here, so it will get None from outside, when you call username_input.
Hope that will help you, and comment if you have further questions. : )
As #Michael Butscher said, if the username you pass the first time doesn't meet the while condition you're giving None back. To fix that you can remove the inner if check and return the username before leaving your function:
def username_input(user):
while len(user) > 12 or not (user.isalnum()):
print("Error: the username must be an alphanumeric value \nand have as maximum 12 characters")
user = input("Type a valid username: ")
return user
If I understand correctly, you want to ask the user for a username and then store their input in a file called Username.txt if it matches certain criteria.
The reason your code returns None at the moment is due to the conditions of the while loop not being satisfied. Because there is no default return statement after the while loop, if the while loop's conditions are not met, the function will exit and return None.
I suggest refactoring your code slightly:
def username_input():
while True:
user = input("Type a valid username: ")
if len(user) <= 12 and user.isalnum():
return user
else:
print("Error: the username must be an alphanumeric value \nand have as maximum 12 characters")
with open("Username.txt", "a") as usr_txt:
usr = username_input()
usr_txt.write(usr)
As a side note, this programming construct is called "loop-and-a-half". It is Python's equivalent of the "do-while" loop. See here for more information.
So here is the issue. I have a series of functions with which an inputString from the user gets checked to meet all of the set password criteria:
Passwords must be at least 5 characters long
Passwords must contain at least one upper case letter
Passwords must contain at least two numbers
Passwords may not contain the characters "E" or "e"
Passwords must include at least one non-alphanumeric character.
A password may not be a frequently used password: 'password', '12345',
'qwerty', 'letmein', 'trustno1', '000000', 'passw0rd,'Password'
My last function attempts to collect all of the functions defined into a single usable module function. There are no errors running the program but there is a bug which always prints, "Invalid! Password must contain special character." Why is that so? And what other bugs or fixed do you guys suggest to make this code more efficient or readable?
def isFiveCharacters(inputString):
while len(inputString) > 5:
return True #print('Contains at least 5 characters, ')
else:
print('Invalid! Password must cantain more than 5 characters')
return False
def hasUpperCase(inputString):
x = any(char.isupper() for char in inputString)
if x == True:
return True #print ('an uppercase letter, ')
if x == False:
print('Invalid! Password must contain an upper case letter')
return False
def hasNumbers(inputString):
count = 0
for char in inputString:
if char == char.isdigit():
count += 1
if count >= 2:
#print ('two numbers, ')
return True
elif count < 2:
print ('Invalid! Password must contain two numbers')
return False
def hasLetterE(inputString):
for char in inputString:
if 'E' and 'e' in inputString:
print('Invalid! Password cannot contain the letter "E"')
return False
else:
#print('does not contain the letter E, ')
return True
#if 'e' in inputString:
# print('Password cannot contain the letter "e"')
# return None
def nonAlphaNumChar(inputString):
special_char = ['!','#','$','%','#','^','&','*']
if inputString == special_char * 2:
#print('a special character, ')
return True
else:
print('Invalid! Password must contain a special character')
return None
def usedPasswords(inputString):
used_passwords = ('password','12345','qwerty','letmein','trustno1','000000','passw0rd','Password')
if used_passwords == inputString:
print('Invalid! Password must be original.')
return False
def passwordCriteria(inputString):
isFiveCharacters(inputString)
hasUpperCase(inputString)
hasNumbers(inputString)
hasLetterE(inputString)
nonAlphaNumChar(inputString)
usedPasswords(inputString)
while inputString == True:
print('Valid Password')
return True
if inputString == False:
print('Error, invalid password')
return False
return None
I am just going to point out the obvious mistake:
You should collect the values returned by the functions like this
valid = isFiveCharacters(inputString)
# then just use the boolean values with an `and`
valid = valid and hasUpperCase(inputString)
valid = valid and hasNumbers(inputString)
# and so on
# then use
if valid:
print("Valid Password")
else:
print("Invalid Password")
I suggest reading about functions the return statement and the while loop in detail and getting a clear understanding of how they work.
The task is to get a user to input a password then, using recursion, make sure it has no vowels in it. If it does then let the user re-enter the password. This is what i have so far:
def passwordCheck(pwd):
"""checks if pwd has any vowels in it."""#doc string
vowels = 'aeiou'#specifies the characters that aren't allowed
if pwd == '':
return 0
elif pwd == None:
return None#Shouldn't be necessary but just in case
elif pwd[0] not in vowels:#checks that the 1st(0th) character is not a vowel
return passwordCheck(pwd[1:])#gets rid of the 1st(0th) character and starts again
elif pwd[0] in vowels:#checks if the 1st(0th) character is a vowel
return 1#if it is, stops the function calls and returns a value
password = str(input('Please enter a password with no vowels in it: '))#asks user to input their new password
x = passwordCheck(password)#checks the password is valid, i.e. no vowels
while x == 1:#when the password entered contains a vowel
print('\nSorry, that is not a valid password.\nYour password cannot contain any vowels.')#tells the user why their password is invalid
password = str(input('\nPlease enter a different password: '))#gives the user a chance to re-enter their password
x = passwordCheck(password)#checks to make sure the new password is valid
print('\nCongratulations, you have entered a valid password!')#tells the user if their desired password is valid
print('\nYou are now able to log on to the system with these credentials.')#could've been included on the previous line but looks neater here
I know this is probably not the most pythonic way of doing it but it works for me in most cases. I'd love to hear a better way but ideally someone can help in the same style. I don't want to just copy someones code without understanding it.
The question i have is dealing with the case where the user enters no password at all. The first if statement:
if pwd == '':
return 0
I thought it just dealt with the case when the string had been fully recursed through, i.e. no vowels, but after a minutes inspection it's obvious this applies to no password as well.
I had also tried using:
if pwd == None:
return something
Now i'm thinking the problem could be because i said:
password = str(input('######'))
but i've fiddled with that as well and still can't can't seem to make that work either! I've tried google and searching stackoverflow but no luck so if anyone has any ideas/solution they think might be helpful I'd be very grateful to hear them. Thank you very much.
My main question is:
How can i differentiate between a string that's empty because it's been recursed through and the user inputting nothing?
Solved.
ended up using
def passwordValid(pwd):
if len(pwd)>0 and passwordCheck(pwd)==0:
return pwd
else: return 'Fail'
password = str(input('Please enter a password with no vowels in it: '))#asks user to input their new password
y = passwordValid(password)#checks the password is valid, i.e. no vowels
while y == 'Fail':#when the password entered contains a vowel
print('\nSorry, that is not a valid password.\nYour password cannot contain any vowels or be empty.')#tells the user why their password is invalid
password = str(input('\nPlease enter a different password: '))#gives the user a chance to re-enter their password
y = passwordValid(password)#checks to make sure the new password is valid
print('\nCongratulations, you have entered a valid password!')#tells the user if their desired password is valid
print('\nYou are now able to log on to the system with these credentials.')#could've been included on the previous line but looks neater here
Thank you Wayne Werner for fixing the title and the main question.
This problem can be broken down into (at least) three distinct subproblems:
check whether a string contains vowels
check whether a string is a valid password (length > X and has vowels)
get a password from the user
Your code should reflect this structure. You could therefore use the following function layout:
def has_vowels(string):
if not string: # check for empty string
return False # empty strings never have vowels
# TODO we have a non-empty string at this point and can use recursion
def is_valid_password(string):
return len(string) > 0 and not has_vowels(string)
def request_password():
while True: # use an endless loop here, we don't won't to repeat
# the "input" statement. We could also change this to
# something like `for i in range(3)` to allow only a limited
# number of tries.
passwd = input('Please enter a password with no vowels in it: ')
# TODO check if input is valid, if yes, return, if no, print an error
Don't attempt to solve both problems with a single method. You have two ditinct critera: no vowels; minimum length.
def isPasswordValid(pwd):
return len(pwd) > 4 and not passwordCheck(password)
x = isPasswordValid(password)
...
You could solve this with recursion by adding another parameter which indicates how many characters have been looped through, but that is clumsy and offers no real benefit.
You can't differentiate between an empty string and an empty string. You can however set the variable to None, or to a string like "__no_string_entered_yet". That said, I don't see why you would need to, see the other answers.
I believe this does what your question asks for:
Not allow an empty password (different than a "blank" password?)
Not allow vowels in the password
I opted not use if/elif/else in favor of structuring it so that valid characters "fall through"
def pwd_check(s):
vowels = 'aeiou'
if len(s) == 0: return False # This is only valid in the first iteration
if s[0] in vowels: return False
if len(s) == 1: return True # Success: a 1 character pwd with no vowels
return pwd_check(s[1:])
I thought about putting checks in to make sure that a string like ' ' was not passed in, but I didn't see that explicitly asked for. pwd_check(password.strip()) solves this problem.
Here's how I like to do.
For the fun, I added conditions of minimum and maximum lengths for the password:
def passwordCheck(pwd,vowels = 'aeiou',minimum=5,maximum=12):
if pwd == '':
return 0,None,None
elif pwd[0] in vowels:
return -1,None,None
else:
y = passwordCheck(pwd[1:])[0]
if y==-1:
return -1,None,None
else:
return y + 1,minimum,maximum
mess = 'Please enter a password with no vowels in it: '
while True:
x,miin,maax = passwordCheckstr(input(mess))
if x==-1:
mess = ('\nSorry, that is not a valid password.\n'
'Your password cannot contain any vowels.\n'
'Please enter a different password: ')
elif x==0:
mess = ('\nSorry, you must enter a password.\n'
'Please do enter a password: ')
elif x<miin:
mess = ('\nSorry, the password must have at least %d characters.\n'
'The string you entered has %d characters.\n'
'Please, enter a new longer password: ' % (miin,x))
elif x>maax:
mess = ('\nSorry, the password must have at most %d characters.\n'
'The string you entered has %d characters.\n'
'Please, enter a new shorter password: ' % (maax,x))
else:
print ('\nCongratulations, you have entered a valid password!\n'
'\nYou are now able to log on to the system with these '
'credentials.')
break
edit
Another kind of algorithm.
I wasn't satisfied to return such tuple as -1,None,None
def check_password(forbidden,minimum,maximum):
def passwordCheck(pwd,cnt=0,forbid = forbidden,
miin=minimum,maax = maximum):
# cnt is the number of preceding turns of recursion
# that have been already executed.
if pwd == '':
if cnt==0:
# cnt==0 means that it's the first turn of recursion
# since pwd is '', it means no entry has been done
return 0
elif cnt<miin:
return -3
elif cnt>maax:
return -2
elif pwd[0] in forbid:
return -1
else:
if cnt in (-3,-2,-1):
return cnt
else:
return passwordCheck( pwd[1:] , cnt+1 )
mess = 'Please enter a password with no vowels in it: '
while True:
x = str(raw_input(mess)).strip()
y = passwordCheck(x)
if y==0: # inexistent string
mess = ('\nSorry, you must enter a password.\n'
'Please do enter a password: ')
elif y==-1: # string contains a vowel
mess = ('\nSorry, that is not a valid password.\n'
'Your password cannot contain any vowels.\n'
'Please enter a different password: ')
elif y==-2: # string too long
mess = ('\nSorry, the password must have at most %d characters.\n'
'The string you entered has %d characters.\n'
'Please, enter a new shorter password: ' % (maximum,len(x)))
elif y==-3: # string too short
mess = ('\nSorry, the password must have at least %d characters.\n'
'The string you entered has %d characters.\n'
'Please, enter a new longer password: ' % (minimum,len(x)))
else: # success
print ('\nCongratulations, you have entered a valid password!\n'
'You are now able to log on to the system with these credentials.')
break
# EXECUTION
check_password('aeiou',5,12)