1

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.

10
  • 1
    I guess you meant NewClass3 and NewClass4, right? Furthermore: which verbosity do you want to remove? Do you want to automatize the change of the digit at the end of each argument, depending on the Class name? Commented Dec 20, 2016 at 6:04
  • You make only instances of NewClass1. Also, redefining NewClass1 three times does not make any sense because only the last definition will be available. Commented Dec 20, 2016 at 6:10
  • @Edouardb Thanks for the quickly answer and sorry for my bad description. Verbosity codes means the long child class definitions. I wander is there any simple way to define a new class without inheritance which is just modify some default value of its super class. Commented Dec 20, 2016 at 6:25
  • Why not just use factory functions to supply the defaults? Commented Dec 20, 2016 at 6:27
  • 2
    You say "without inheritance", but then also refer to a super class. You can't have one without the other. If you don't need separate classes, use functools.partial, perhaps. If you do need classes, what you have is probably about as good as you can get. Commented Dec 20, 2016 at 6:35

3 Answers 3

1

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()
Sign up to request clarification or add additional context in comments.

4 Comments

This is indeed much cleaner, but it could lead to trouble down the line if the superclass constructor is changed to do anything more complicated than just assigning the passed-in values to attributes of the instance. So if you do this, I'd suggest at least leaving a comment in the superclass constructor as a reminder to any future coders who might modify it.
@DavidZ: I think you do not even need inheritance in this case. If I were you, I would have done it like I did in the edit that I just did
Yeah, I would probably use a factory function or some such thing too. My comment applies if you are doing inheritance for whatever reason.
Doesn't the second solution actually modify the implementation of the class DB? I thought this is not possible as it is third-party.
0

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.

Comments

0

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()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.