Using global variables to store state: the login function example¶

We'd like to make a function that lets users log in. The function return True on successful login, and False otherwise.

The function locks the user out if there are three consecutive unsuccessful logins.

The function returns different things for the same inputs depending on what happened before. That means that we need to use global variables (or something equivalent) in order to keep track of the state: the information that determines what the function should return based on what happened before.

We saw an example of this before, when we generated pseudorandom numbers (we needed to keep track of what x was).

In [1]:
# login.py

def login(user, password):
    global n_attempts, locked_out # may need to change those
    if locked_out:
        return False
    
    if user not in users:
        n_attempts += 1
        if n_attempts == 3:
            locked_out = True
        return False
    if passwords[users.index(user)] != password: # can now safely use users.index(user)
                                                 # since user is in users
        n_attempts += 1
        if n_attempts == 3:
            locked_out = True
        return False
        
    # N.B., could also user if user not in users or passowrds[users.index(user)] != password
    # because of short-circuiting -- we'll discuss this later
    n_attempts = 0 # succesful attempt: reset n_attempts
    return True
        



def initialize():
    global users, passwords
    global n_attempts, locked_out
    
    users = ["guerzhoy", "cluett", "stangeby"]
    passwords = ["ILovePython", "matrix", "rigorous"]
    
    n_attempts = 0 # initially, 0 consecutive failed attempts
    locked_out = False # initialliy, not locked out
    
    
initialize() # call the function outside the main block
In [ ]:
# user_login.py

import login  # intialize is run

if __name__ == __main__:
    print(login.login("guerzhoy", "ILovePython")) # True
    print(login.login("guerzhoy", "ILikePython")) # False
    print(login.login("guerzhoy", "ILikePython")) # False
    print(login.login("guerzhoy", "ILikePython")) # False, locked out
    print(login.login("guerzhoy", "ILovePython")) # False, because locked out