ansvver
ansvver

Reputation: 317

Any easy way to specify default value of arguments in Python class constructor without writing inheritance?

Is there any easy to get a new class based on an old class which is just set some default arguments value of the old class? Code like this:

class DB():
    def __init__(self, ip, port, dbname, table):
        self.ip = ip
        self.port = port
        self.dbname = dbname
        self.table = table

    def process(self):
        print self.ip, self.port, self.dbname, self.table

Now I need to get a set of new classes with some default values of OldClass.a, OldClass.b, OldClass.c, I will do like below:

class UserDB(DB):
    def __init__(self, dbname, table):
        OldClass.__init__(self, ip='user.db.com', port='1234', dbname=dbname, table=table)

class ProdDB(DB):
    def __init__(self, dbname, table):
        OldClass.__init__(self, ip='prod.db.com', port='1314', dbname=dbname, table=table)

class CommentDB(DB):
    def __init__(self, dbname, table):
        OldClass.__init__(self, ip='comment.db.com', port='1024', dbname=dbname, table=table)

class MeetingDB(DB):
    def __init__(self, dbname, table):
        OldClass.__init__(self, ip='meeting.db.com', port='8888', dbname=dbname, table=table)

userDB = UserDB('user', 'new')
userDB.process()
prodDB = ProdDB('prod', 'lala')
prodDB.process()
commentDB = UserDB('comm', 'gg')
commentDB.process()
meetingDB = MeetingDB('met', 'ok')
meetingDB.process()

I remember there are some tricks to simplify these child class verbosity codes. Any advice is welcome. Thanks in advance.

Upvotes: 1

Views: 117

Answers (3)

hemraj
hemraj

Reputation: 1034

Inheritance is an awesome thing:

class DB():
    def __init__(self, ip, port, dbname, table):
        self.ip = ip
        self.port = port
        self.dbname = dbname
        self.table = table

    def process(self):
        print self.ip, self.port, self.dbname, self.table


class UserDB(DB):
    def child_func(self):
        print "We Dont share Email Ids :)"

a = UserDB("151.101.1.69", 1999, "UsersInfo", "user_log")
a.process()
a.child_func()


b = UserDB("151.101.1.69", 2001, "ClickInfo", "click_log")
b.process()
b.child_func()

Upvotes: 0

Mike Müller
Mike Müller

Reputation: 85442

You can solve any problem with another level of indirection.;) How about having another class in between MyDB?:

from __future__ import print_function  # for legacy Python


class DB():
    def __init__(self, ip, port, dbname, table):
        self.ip = ip
        self.port = port
        self.dbname = dbname
        self.table = table

    def process(self):
        print(self.ip, self.port, self.dbname, self.table)

Add your class that overrides the __init__():

class MyDB(DB):
    def __init__(self, dbname, table):
        super(MyDB, self).__init__(self.ip, self.port, dbname, table)

Now use with class attributes. These classes do not need an __init__() anymore::

class UserDB(MyDB):
    ip = 'user.db.com'
    port = '1234'

class ProdDB(MyDB):
    ip = 'prod.db.com'
    port = '1314'

Making two test instances:

user_db = UserDB('user', 'new')
user_db.process()

prod_db = ProdDB('prod', 'lala')
prod_db.process()

Output:

user.db.com 1234 user new
prod.db.com 1314 prod lala

This provides a rather declarative way of doing things. It should pretty readable, especially if the classes UserDB and ProdDB don't have an methods.

Since self.ip and self.port, do not exist in the instance self, the search will proceed to the class attributes of the current class, i.e. UserDB if we work with UserDB.

Upvotes: 0

Moinuddin Quadri
Moinuddin Quadri

Reputation: 48077

You do not need to call parent's class' __init__ as you just want to set the values to the instance properties. You may simply do:

class DB():
    def __init__(self, dbname, table):
        self.dbname = dbname
        self.table = table
        self.ip = 'user.db.com'
        self.port = '1234'

I think it is much cleaner. In fact you do not need 4 child classes. You may do it within single class using parameter to differentiate the category of each db as:

class DB():

    # Database type configuration
    db_type_conf = {
        'user': {
            'ip': 'xx.xx.xx',
            'port': 'xxxx',
        },
        'comment': {
            'ip': 'xx.xx.xx',
            'port': 'xxxx',
        },
        'prod': {
            'ip': 'xx.xx.xx',
            'port': 'xxxx',
        },
        'meeting': {
            'ip': 'xx.xx.xx',
            'port': 'xxxx',
        }
    }

    def __init__(self, db_type, dbname, table):
        self.dbname = dbname
        self.table = table
        self.port, self.ip = self._get_port_and_ip_from_db_type(db_type)
        #                    return port and ip based on `db_type` ^

    @staticmethod
    def _get_port_and_ip_from_db_type(db_type):
       db_type_conf = self.__class__.db_type_conf[db_type]
       return db_type_conf['port'], db_type_conf['ip']

    def process(self):
        print self.ip, self.port, self.dbname, self.table

For creating the objects, you may simply do:

user_db = DB('user', 'user', 'new')
user_db.process()

Upvotes: 1

Related Questions