0

I am trying to write a class that allows users to register on a platform with a username, but checks that this username does not exist in the database.

I have this code:

class Freelancer:
    """Leaving this blank for now while I explore the functionality """
    number_of_sales = 0
    available_niches = ["Graphic design", "Art", "Data Analysis", "Music", "Business", "Writing and Translations"]
    usernames = []

    def __init__(self, username):
        self.username = _check_username(username)
    
    def _check_username(self, username):
        if self.username in Freelancer.usernames:
            print("This username already exist on our database, consider choosing another one")
        else:
            self.username = username
            Freelancer.usernames.append(self.username)
            print("You have successfully setup a username on our platform")

which I tested like so:

David = Freelancer("dave23")

But I got an exception: NameError: name '_check_username' is not defined. What is wrong with the code? How can I call a private method from __init__?

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
JA-pythonista
  • 1,225
  • 1
  • 21
  • 44
  • 4
    Need: `self.username = self.__check_username(username)` to i.e. needs 'self.' [call methods within class](https://stackoverflow.com/questions/5615648/python-call-function-within-class). Need `__` (i.e. double dash) to make method private [Private Methods](https://www.geeksforgeeks.org/private-methods-in-python/) – DarrylG Apr 11 '20 at 12:04
  • Great! Thank you! – JA-pythonista Apr 11 '20 at 12:15

2 Answers2

3

You missed self before calling private method.

def __init__(self, username):
    self.username = self._check_username(username)

If it is still gives error like: 'Freelancer' object has no attribute 'username' define username variable

FAHAD SIDDIQUI
  • 631
  • 4
  • 22
  • 1
    Need double underscores to make method private, otherwise it's still accessible by public i.e. `bill = Freelancer('bill'); bill._check_username('bill')` works [see](https://www.geeksforgeeks.org/private-methods-in-python/) – DarrylG Apr 11 '20 at 12:21
  • 1
    @DarrylG the name mangling caused by a leading double underscore is not proper "privacy". Using a single leading underscore is the standard convention, as Python lacks real functionality for `private` attributes. – Karl Knechtel Oct 18 '22 at 18:27
-1

First of all, __init__ is not the constructor. Note that __init__(self) already has the object (self), so it was already constructed before calling __init__. (The real constructor in Python is __new__). Python does not have private methods, no matter how many underscores you add.

This should work:

def __init__(self, username):
    self.username = self.check_username(username) 

def check_username(self, username):
   ...

You could add the leading underscore to indicate that the method is for internal use only.

There is however another mistake in the code. It should be:

def _check_username(self, username):
    if self.username in self.usernames:  # <-----
        print("This username already exist on our database, consider choosing another one")

    else:            
        self.usernames.append(self.username)  # <----- 
        return username

You are manipulating the class. That means that if the class is instantiated again usernames is not empty.

Alex
  • 5,759
  • 1
  • 32
  • 47
  • "You are manipulating the class." This is **intentional**. The goal of OP's code is to remember the usernames of all instances that are created. – Karl Knechtel Oct 18 '22 at 18:28
  • @KarlKnechtel right, it could be. But the code is a bit weird anyway. if `self.usernames()` was a call to a database it would make more sense. – Alex Oct 19 '22 at 09:24