Reputation: 45
I have a simple program that checks the user's 'passcode' that either allows them access or denies them access.
If the user types in the correct passcode, the print statement "Login successful! Passcode used:", passcode" is printed, however, if the passcode is wrong, it simply asks for their passcode again without printing the statement "Login unsuccessful."...
Why is this? Thankyou.
LoginCorrect = 0
lst = ['1234', '2345', '3456', '4567', '5678', '6789']
while LoginCorrect == 0:
passcode = input("Please enter your passcode: ")
for item in lst:
if item == passcode:
print("Login successful! Passcode used:", passcode)
LoginCorrect = 1
if not item in lst == False:
print("Login unsuccessful.")
Upvotes: 0
Views: 157
Reputation: 18625
To answer your specific question: not item in lst
works fine, but
not item in lst == False
is evaluated differently than you probably expect.
Python converts chains of logical tests like (a == b == c)
or (a in b in c)
to (a == b) and (b == c)
or (a in b) and (b in c)
. It also does this When it
sees in
and ==
in the same expression. So not item in lst == False
is evaluated as
not ((item in lst) and (lst == False))
, which is always True
. (Without the not
, it
would always be False
, which may be what prompted your original question).
You could fix this by putting parentheses around your first test: (not item in lst) == False
(or maybe you mean True
?). But a better way to write this test would be if item not in lst:
.
There are also a couple of other problems with the organization of your code, which
I've pointed out in comments below:
LoginCorrect = 0 # probably better to use True/False here
lst = ['1234', '2345', '3456', '4567', '5678', '6789']
while LoginCorrect == 0:
# The next line will not work right on Python 2.x, which has a different
# input() function; if your code might run on 2.x you should adjust for that.
passcode = input("Please enter your passcode: ")
for item in lst:
if item == passcode:
print("Login successful! Passcode used:", passcode)
LoginCorrect = 1
# you could use a 'break' here to avoid comparing to more items
# As noted above, `if item not in lst:` would work better for the next line.
# This test should also probably occur after the `for` loop instead of
# inside it, and act based on `LoginCorrect` instead of `item`. As it is,
# you are testing whether `item` is in `lst`, which it always is, and you
# are doing this test once for each `item`, which is more checks than needed.
if not item in lst == False:
print("Login unsuccessful.")
You mentioned in a comment on a different answer that you have to use a for
loop to
test the passcode against each item. If that's true, then the revised code below
could work well:
try:
# Python 2 compatibility
input = raw_input
except NameError:
pass
LoginCorrect = False
lst = ['1234', '2345', '3456', '4567', '5678', '6789']
while not LoginCorrect:
passcode = input("Please enter your passcode: ")
for item in lst:
if item == passcode:
print("Login successful! Passcode used:", passcode)
LoginCorrect = True
break
if not LoginCorrect:
print("Login unsuccessful.")
Or, if you are willing to drop the for
loop, you can make your code much simpler:
try:
# Python 2 compatibility
input = raw_input
except NameError:
pass
lst = ['1234', '2345', '3456', '4567', '5678', '6789']
while True:
passcode = input("Please enter your passcode: ")
if passcode in lst:
print("Login successful! Passcode used:", passcode)
break
else:
print("Login unsuccessful.")
Upvotes: 1
Reputation: 55469
The logic of your code is somewhat unclear. I think you meant to do something like this:
LoginCorrect = 0
lst = ['1234', '2345', '3456', '4567', '5678', '6789']
while LoginCorrect == 0:
passcode = input("Please enter your passcode: ")
for item in lst:
if item == passcode:
print("Login successful! Passcode used:", passcode)
LoginCorrect = 1
break
if passcode not in lst:
print("Login unsuccessful.")
BTW, it would be more usual in Python to use the booleans False
and True
for your LoginCorrect
flag, eg
lst = ['1234', '2345', '3456', '4567', '5678', '6789']
LoginCorrect = False
while not LoginCorrect:
passcode = input("Please enter your passcode: ")
for item in lst:
if item == passcode:
print("Login successful! Passcode used:", passcode)
LoginCorrect = True
break
if passcode not in lst:
print("Login unsuccessful.")
However, as others have said, it's inefficient to use a Python loop to test if passcode
is in lst
. An in
test does that more efficiently, and it would be even more efficient if lst
were instead a set
of valid passcodes.
lst = {'1234', '2345', '3456', '4567', '5678', '6789'}
while True:
passcode = input("Please enter your passcode: ")
if passcode in lst:
print("Login successful! Passcode used:", passcode)
break
print("Login unsuccessful.")
I have to mention that one of the if
statements in your code does not do what you think it does:
if not item in lst == False:
To explain why, I need to take a slight detour. :)
Python syntax supports the chaining of relational operators. This allows you to do things like
if 0 <= a < 5:
or even
if 0 <= a < 5 <= b < 10:
The chained test 0 <= a < 5
is equivalent to (0 <= a) and (a < 5)
,
and 0 <= a < 5 <= b < 10
is equivalent to
(0 <= a) and (a < 5) and (5 <= b) and (b < 10)
The and
operator short-circuits, which means that in
left_expression and right_expression
it only evaluates right_expression
if bool(left_expression)
is True. So in those chained tests, Python works from left to right, breaking out of the chain if it detects a falsey result at any stage.
Also, in chained tests any of the intermediate expressions are guaranteed to be evaluated at most once. Eg, in f() < g() < h()
the function g
is called once at most, and it will only be called if f()
returns a non-falsey result.
Now, to get back to your code. :)
The in
operator is a relational operator, so it can be used in chained tests. So
if item in lst == True:
is equivalent to
if (item in lst) and (lst == True):
and
if not item in lst == False:
is equivalent to
if not ((item in lst) and (lst == False)):
I think you'll agree that's not what you meant to say! :)
And now you should be able to understand why this weird piece of code prints True
ab = ('a', 'b')
print('b' in ab in [('a', 'b'), 'c'])
Upvotes: 1
Reputation: 22443
How about a while
statement with continue
and break
?
lst = ['1234', '2345', '3456', '4567', '5678', '6789']
while True:
passcode = input('Please enter your passcode: ')
if passcode not in lst:
continue
else:
print("Login successful! Passcode used:", passcode)
break
You state "if the passcode is wrong, it simply asks for their passcode again without printing the statement "Login unsuccessful."
That being the case, why are you coding for "Login Unsuccessful" ?
Upvotes: 0
Reputation: 311163
You're over complicating things. Instead of iterating over the list yourself, you could just check if the passcode
is there:
LoginCorrect = False
lst = ['1234', '2345', '3456', '4567', '5678', '6789']
while LoginCorrect:
passcode = input("Please enter your passcode: ")
if passcode in lst:
print("Login successful! Passcode used:", passcode)
LoginCorrect = True
else:
print("Login unsuccessful.")
Upvotes: 4
Reputation: 1263
I hope that this is just an excersise and not a production code to perform login, because it is super not secured.
Here is a working version of your snippet:
lst = ['1234', '2345', '3456', '4567', '5678', '6789']
LoginCorrect = False
while not LoginCorrect:
passcode = input("Please enter your passcode: ")
if passcode in lst:
print("Login successful! Passcode used:", passcode)
LoginCorrect = True
else:
print("Login unsuccessful.")
Upvotes: 0