I have a class that can interface with either Oracle or MySQL. The class is initialized with a keyword of either "Oracle" or "MySQL" and a few other parameters that are standard for both database types (what to print, whether or not to stop on an exception, etc.).
It was easy enough to add if Oracle do A, elif MySQL do B
as necessary when I began, but as I add more specialized code that only applies to one database type, this is becoming ugly. I've split the class into two, one for Oracle and one for MySQL, with some shared functions to avoid duplicate code.
What is the most Pythonic way to handle calling these new classes? Do I create a wrapper function/class that uses this same keyword and returns the correct class? Do I change all of my code that calls the old generic class to call the correct DB-specific class?
I'll gladly mock up some example code if needed, but I didn't think it was necessary. Thanks in advance for any help!
Probably the most common approach to spreading a class's code over multiple files is to use subclassing, with the base class in one module, and the (or each) subclass, in its own separate module.
No, you can define multiple classes (and functions, etc.) in a single file. A file is also called a module. To use the classes/functions defined in the module/file, you will need to import the module/file.
Practical Data Science using Python So a module is a unit or reuse. The rule is this: a module is the unit of reuse. Everything in Python libraries and other Python applications is either a module or a package of modules. There is no limit on how many classes one can put in a file or a module.
Do I create a wrapper function/class that uses this same keyword and returns the correct class?
That's the idea. Such a function is called a factory function:
def connect_to(db, *args):
if db == "MySQL":
return MySQL(*args)
elif db == "Oracle":
return Oracle(*args)
else:
raise ValueError("unknown database type: %r" % db)
Make sure that both database classes have the same API. You can achieve this either with duck typing or with abstract base classes (ABCs); the latter are mostly useful if functionality is shared between the classes, or if you want to do isinstance
checks to find out if an object represents a database connection.
In the case of shared functionality, the template method pattern often comes in handy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With