100 days of code: Day 28 - attributes

Last modified on 2020-07-06

Source: 100-days-of-code.

Attributes (variables inside a class) are prefixed with self and are available to every method in the class and any instance can access them. When I create an instance I can set attributes with default values that do not have to be passed as parameters.

Here is a users.py class I wrote with attributes for login_attempts and max_login_attempts

class User:
    """A simple attempt to represent a user."""


    def __init__(self, first_name, last_name, city, country):
        self.first_name = first_name
        self.last_name = last_name
        self.city = city
        self.country = country
        self.login_attempts = 0
        self.max_login_attempts = 3

        [...]

I later modify self.login_attempts internally by calling methods to incrementally update the count, and reset the counter back to zero again for the next instance …

    def increment_login_attempts(self):
        """Track login attempts."""
        self.login_attempts += 1


    def reset_login_attempts(self):
        """Reset login counter to zero."""
        self.login_attempts = 0

    [...]

All together now …

class User:
    """A simple attempt to represent a user."""


    def __init__(self, first_name, last_name, city, country):
        self.first_name = first_name
        self.last_name = last_name
        self.city = city
        self.country = country
        self.login_attempts = 0
        self.max_login_attempts = 3


    def increment_login_attempts(self):
        """Track login attempts."""
        self.login_attempts += 1


    def reset_login_attempts(self):
        """Reset login counter to zero."""
        self.login_attempts = 0


    def describe_user(self):
        """A summary of a user's information."""
        print(f"\nUsername: {self.first_name} {self.last_name}")
        print(f"Location: {self.city}, {self.country}")


    def greet_user(self):
        """A personalized greeting for a user."""
        play = input(f"Hello {self.first_name}! "
                + "Would you like to play a game? Y/N > ")
        if play.lower() == 'y':
            # there is no 'correct' login, its just playing out a loop
            while self.login_attempts < self.max_login_attempts:
                login = input("Enter login: ")
                print(f"Login {login} is incorrect.")
                self.increment_login_attempts()
                print(f"Login attempts: {self.login_attempts}")
            print("Maximum login attempt limit reached. No game for you. :-(")
        else:
            print("OK. No game.")


# Create user instances.
user_0 = User('Clint', 'Westwood', 'Whitehorse', 'Canada')
user_1 = User('Natalie', 'Portwoman', 'Los Angeles', 'USA')
user_2 = User('Roger', 'Nailstein', 'Zurich', 'Switzerland')

# Logins
user_0.describe_user()
user_0.greet_user()
user_0.reset_login_attempts()

user_1.describe_user()
user_1.greet_user()
user_1.reset_login_attempts()

user_2.describe_user()
user_2.greet_user()
user_2.reset_login_attempts()

Run …

$ python3 users.py

Username: Clint Westwood
Location: Whitehorse, Canada
Hello Clint! Would you like to play a game? Y/N > y
Enter login: clint
Login clint is incorrect.
Login attempts: 1
Enter login: westwood
Login westwood is incorrect.
Login attempts: 2
Enter login: cwest
Login cwest is incorrect.
Login attempts: 3
Maximum login attempt limit reached. No game for you. :-(

Username: Natalie Portwoman
Location: Los Angeles, USA
Hello Natalie! Would you like to play a game? Y/N > N
OK. No game.

Username: Roger Nailstein
Location: Zurich, Switzerland
Hello Roger! Would you like to play a game? Y/N > N
OK. No game.

Happy hacking!