rajaneesh
rajaneesh

Reputation: 219

Error when using a Python constructor

class fileDetails :

    def __init__(self,host,usr,pwd,database):
        self.host=host
        self.usr.usr
        self.pwd=pwd
        self.database=database

    def __init__(self,connection,sql,path):
        self.connection=mysql_connection()
        self.sql=sql
        self.path=path

If I use the constructor then it gives an error:

onnetction = fileDetails('localhost',"root","",'bulsorbit')
TypeError: __init__() takes exactly 4 arguments (5 given)

Upvotes: 1

Views: 697

Answers (6)

drrlvn
drrlvn

Reputation: 8437

In Python the functions in a class are stored internally in a dictionary (remember that constructors are just regular functions), and so only one function of the same name can exist. Therefore, when defining more than one functions with the same name the last one will overwrite all the previously defined ones and you'll end up with only one function.

I suggest you look into keyword and default arguments to see the proper way of achieving what you want.

Upvotes: 1

Wojciech Bederski
Wojciech Bederski

Reputation: 3922

On the side note: if you really, really, reallllllyyy must do JiP (Java in Python) then multiple dispatch methods are possible with some additional code eg. here and even beter: here by BDFL.

Personally I try to avoid using them.

Upvotes: 0

ars
ars

Reputation: 123498

Here's one way to achieve this:

class FileDetails:
    def __init__(self, *args, **kwargs):
        if len(args) == 3:
            self.conn, self.sql, self.path = args
        elif len(args) == 4:
            self.host, self.usr, self.pw, self.db = args
        else:
            # handle appropriately

fd1 = FileDetail('connstring', 'select * from foo', '/some/path')
print fd1.conn, fd1.sql, fd1.path

fd2 = FileDetail('host', 'user', 'pass', 'somedb')
print fd2.conn, fd2.usr, fd2.pw, fd2.db

Of course, you should do the appropriate type checking and error handling in the constructor.

Upvotes: 0

kjfletch
kjfletch

Reputation: 5494

Define a single constructor with optional arguments.

def __init__(self,host='host',usr='user',pwd='pwd',database='db',connection=None,sql=None,path=None):
  if connection:
    # however you want to store your connection
    self.sql=sql
    self.path=path
  else:
    self.host=host
    self.usr.usr
    self.pwd=pwd
    self.database=database

Or something of the sort.

Upvotes: 4

ThibThib
ThibThib

Reputation: 8210

The overloading of the constructor (or any other function) is not allowed in python. So you cannot define two __init__ functions for your class.

You can have a look to this post or this one

The main ideas are to use default values or to create 'alternate constructors' or to check the number and the type of your args in order to choose which method to apply.

def __init__(self, **args):

Then args will be a dictionary containing all the parameters. So you will be able to make the difference between

connection = fileDetails(host='localhost',usr="root",pwd="",database='bulsorbit')

and

connection = fileDetails(connection="...",sql="...",path="...")

Upvotes: 10

sunqiang
sunqiang

Reputation: 6492

maybe you can use len() to choose the right branch:

class Foo(object):
    def __init__(self, *args):
        if len(args) == 4: # network
            self.host = args[0]
            self.user = args[1]
            self.pwd = args[2]
            self.database = args[3]
        elif len(args) == 3: # database
            self.connection = mysql_connection() # maybe it's args[0]?
            self.sql = args[1]
            self.path = args[2]

def main():

    foo = Foo('localhost',"root","",'bulsorbit')
    print foo.host
if __name__ == "__main__":
    main()
# output
# localhost

but, sine Explicit is better than implicit. maybe this is workable too:

class Foo(object):
    def __init__(self, initdata):
        if initdata['style'] == 'network':
            self.host = initdata['host']
            self.usr = initdata['usr']
            self.pwd = initdata['pwd']
            self.database = initdata['database']
        elif initdata[style] == 'database':
            self.connection = mysql_connection()
            self.sql = initdata['sql']
            self.path = initdata['path']
def main():
    data = dict({'style': 'network',
                 'host': 'localhost',
                 'usr': 'root',
                 'pwd': '',
                 'database': 'database'})
    foo = Foo(data)
    print foo.host
if __name__ == "__main__":
    main()
# output
# localhost

Upvotes: 1

Related Questions