6

I have the following class which is being subclassed:

class ConnectionManager(object):

    def __init__(self, type=None):

        self.type = None

        self.host = None
        self.username = None
        self.password = None
        self.database = None
        self.port = None


    def _setup_connection(self, type):
        pass

I then have a specific manager for various database. And I can call those like this:

c = MySQLConnectionManager()
c._setup_connection(...)

However, is there a way to do the following instead?

c = ConnectionManager("MySQL")
c._setup_connection(x,y,z) # this would call the MySQLConnectionManager, 
                           # not the ConnectionManager

Basically, I want to be able to call things in reverse order, is that possible?

3
  • Perhaps you should be implementing __new__() - that lets you create and return an instance of an appropriate subclass, based on the parameters that were passed. __init__() is too late to do any such thing, the object has already been created. Commented Nov 19, 2018 at 23:17
  • @jasonharper could you please show how that would be done in the above? Commented Nov 19, 2018 at 23:19
  • @jasonharper what would I return in the __new__ method? Would it be return MySQLConnectionManager() ? Commented Nov 19, 2018 at 23:32

1 Answer 1

3

One approach would be to use the static factory method pattern. Leaving out non-relevant code for brevity:

class ConnectionManager:
    # Create based on class name:

    @staticmethod
    def factory(type):
        if type == "mysql": return MySqlConnectionManager()
        if type == "psql": return PostgresConnectionManager()
        else:
            # you could raise an exception here
            print("Invalid subtype!")

class MySqlConnectionManager(ConnectionManager):
    def connect(self): print("Connecting to MySQL")

class PostgresConnectionManager(ConnectionManager):
    def connect(self): print("Connecting to Postgres")

Use the factory method to create subclass instances:

psql = ConnectionManager.factory("psql")
mysql = ConnectionManager.factory("mysql")

Then use your subclass objects as needed:

psql.connect()  # "Connecting to Postgres"
mysql.connect()  # "Connecting to MySQL" 
Sign up to request clarification or add additional context in comments.

5 Comments

thanks, this certainly seems like the easiest approach. Out of curiosity, what would be the difference between using this approach and using the __new__() item?
also, what does the line factory = staticmethod(factory) do?
@HenryH updated to use the staticmethod decorator, which allows us to call the decorated method factory from an uninstantiated object.
Classes don’t need to explicitly inherit from object in python 3.
@HenryH there are a few good reasons to use a static factory method rather than use the constructor (__new__) - one important distinction is that the static factory method can be meaningfully named.