Reputation: 1282
I was wondering if passing module objects to a class or object which requires it rather than using import
might not be a bad idea, as it avoids hard dependencies on those modules.
I was wondering if someone more aware of the Python Zen than I might be able to explain why this is a terrible/not terrible idea?
Upvotes: 46
Views: 23786
Reputation: 121
I'm late for the game, but I have just learned a way to do this and wanted to share:
chosen_config='moduleName' #string, relative path. example: 'configurations.local.logistic'. You would take this from input, or the command line, or something like that
import importlib
config=importlib.import_module(chosen_config,package='myPackage')
#...do stuff...
data=pd.read_csv(config.dataFile)
#...more stuff...
save(config.outputFile)
Is equivalent to:
import moduleName as config
But I let the user (aka Future Me or someone I trust) decide which module to import.
Use case (my situation): You want to run a series of experiments with a sequence of different settings that will affect several scripts. You have stored the settings for each experiment in a dedicated config file. You want to run all the tasks without modifying your code.
Upvotes: 5
Reputation: 184395
What you're talking about is called dependency injection and is considered a good practice for making your code testable. I don't think there's anything about Python that would make it unPythonic or a bad practice.
There are other ways you could do it in Python, for example by importing different modules depending on some kind of flag you pass in:
class Foo(object):
def __init__(self, testing=False):
if testing:
import module_test as module
else:
import module
self.module = module
But passing a reference to the module you wish to use is more flexible, separates concerns better, and is no less Pythonic than passing a reference to a class or instance (or string or integer) you wish to use.
For the ordinary (non-test) use case, you can use a default argument value:
class Foo(object):
def __init__(self, module=None):
if not module:
import module
self.module = module
Upvotes: 48
Reputation: 69248
If the class in question can use one of several different modules, then it could make sense to pass in the one you want it to use.
In every situation I have encountered so far, however, the modules needed are certain, so using import
would be preferred.
Upvotes: 4