0

Got a class and want 2 different constructors that make different things happen depending on the number of parameters given. I thought that it should work if a constructor has a different number of parameters..?..

class User:
    def __init__(self, username, password, doB):
        self.username=username
        self.password=md5hash(password)
        self.doB=doB
    def __init__(self, username, cursor): 
        self.username=username
        cursor.execute("SELECT password, doB, doAccount, favourites FROM useraccount WHERE username = %s;", (self.username,))
        userData=cursor.fetchone()
        self.password = userData[0]
        self.doB = userData[1]
        self.doA = userData[2]
        self.favourites = userData[3]
    def printDoB(self):
        print(self.doB)
    def userGetter(self):
        return self.username
    
        

u1=User("matt", "1233", "11-10-02")
u1.printDoB()

User.__init__() takes 3 positional arguments but 4 were given

ChrisGPT was on strike
  • 127,765
  • 105
  • 273
  • 257
DroopyTuna
  • 11
  • 1
  • 2
    This is out of scope for your question, but I also wanted to point out there is potential for SQL injection within the constructor you've used with a `cursor` argument. Formatting a user provided string into a raw SQL statement allows for arbitrary SQL to be appended to the query. This may not be an issue if a user never controls these parameters, but I just wanted to ensure you are aware of this security vulnerability with large implications. – h0r53 Aug 29 '23 at 14:57
  • @h0r53 important to point out, python does not support overloading *at all*. – juanpa.arrivillaga Aug 29 '23 at 15:14
  • The way this is done is to create an alternative constructor. You can see this in the standard library, e.g. itertools.chain() vs itertools.chain.from_iterable() – mikb Aug 30 '23 at 00:35
  • @juanpa.arrivillaga I would disagree that python doesn't support overloading. In particular, functools.single_dispatch() achieves a lot of what in other languages is done by overloading. – mikb Aug 30 '23 at 01:04
  • @mikb of course, there are alternatives that allow you to achieve similar end results. But method overloading, i.e. ad hoc polymorphism, is a kind of static dispatch, where method resolution is based on declared parameters (number and types), and is decided prior to runtime (compile time). single dispatch is a form of dynamic dispatch where the *runtime types* ultimately decide which method is used. And also, you would really want multiple dispatch to achieve the same thing as method overloading that you have in Java or C++ – juanpa.arrivillaga Aug 30 '23 at 01:37

2 Answers2

2

No, you cannot have multiple __init__() methods in a class. In fact, you cannot overload methods in python classes at all.

Note that __init__() is NOT a constructor because the object has been created in memory before this method is called. You will need to find another solution.

It appears to me that you are trying to do too many things in a single class and violate the Single Responsibility Principle. I recommend that you separate the database call from the object initialization. You might want to look at a database library such as SqlAlchemy.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
1

In Python, you cannot have multiple __init__ methods with different numbers of parameters. However, you can achieve similar functionality by providing default values for some of the parameters.

class User:
    def __init__(self, username, password=None, doB=None, cursor=None):
        self.username = username
        if password is not None and doB is not None:
            self.password = md5hash(password)
            self.doB = doB
        elif cursor is not None:
            cursor.execute("SELECT password, doB, doAccount, favourites FROM useraccount WHERE username = %s;", (self.username,))
            userData = cursor.fetchone()
            self.password = userData[0]
            self.doB = userData[1]
            self.doA = userData[2]
            self.favourites = userData[3]
        else:
            raise ValueError("Invalid parameters provided.")
    
    def printDoB(self):
        print(self.doB)
    
    def userGetter(self):
        return self.username


__init__ is not a constructor

Sauron
  • 551
  • 2
  • 11