My question is about finding the "good way" of defining a function whose implementation differs according to a given criterion. This function will be called from several scripts, therefore I must place it in a module.
For the sake of example, my criterion concerns which platform the script is run on, but be clear that the test could bear upon anything. My functions allow persistent definition/retrieving of environment variables, so I created a module named persistenv.py according to the following scheme (SOLUTION 1) :
# CROSS-PLATFORM PART
def my_function1() :
# ... body1 ...
# WINDOWS-ONLY PART
if sys.platform.lower().startswith('win') :
def my_function2() :
# ...body2 for Windows...
# LINUX-ONLY PART
elif sys.platform.lower().startswith('linux') :
def my_function2() :
# ...body2 for Linux...
else :
raise ImportError('Your platform is not supported')
The above introduces two possible definitions of the same function in a single module. Anyway, it sounded pretty much cleaner to me than testing the platform each time the function was called (SOLUTION 2) :
# CROSS-PLATFORM PART
def my_function1() :
# ... body1 ...
def my_function2() :
# WINDOWS-ONLY PART
if sys.platform.lower().startswith('win') :
# ...body2 for Windows...
# LINUX-ONLY PART
elif sys.platform.lower().startswith('linux') :
# ...body2 for Linux...
I found another approach in which each platform-specific part was extracted into its own module, and then imported conditionally in persistenv.py (SOLUTION 3) :
# CROSS-PLATFORM PART
def my_function1() :
# ... body1 ...
# WINDOWS-ONLY PART
if sys.platform.lower().startswith('win') :
from persistenv_win import my_function2
# LINUX-ONLY PART
elif sys.platform.lower().startswith('linux') :
from persistenv_linux import my_function2
else :
raise ImportError('Your platform is not supported')
Up to now, I reached the following conclusions (and got the following questions) :
SOLUTION 2 should hardly be used, particularly if you have several platform-specific functions my_function2, my_function3, my_function4... (as you would have to repeat the test in each of them)
SOLUTION 1 appears quite simple (no extra files, a single test), but I wonder how does Python behave (internally) if one needs to call "from persistenv import my_function2" ?
SOLUTION 3 seems more Pythonic (used in built-in implementations, os.path for instance), but can't it be problematic when persistenv.py, persistenv_win.py and persistenv_linux.py are part of a same package (among other modules) which I would globally import by doing "import my_package" in the main script ?
The word “function” has different meanings in mathematics and programming. In programming it refers to a named sequence of operations that perform a computation. For example, the function sqrt() which is defined in the math module computes the square root of a given value: In [1]: from math import sqrt sqrt(4)
A module is a distinct assembly of components that can be easily added, removed or replaced in a larger system. Generally, a module is not functional on its own. In computer hardware, a module is a component that is designed for easy replacement.
To call a function, you have to write the function name followed by parenthesis containing the parameters you want to pass to the method.
You need to use the import keyword along with the desired module name. When interpreter comes across an import statement, it imports the module to your current program. You can use the functions inside a module by using a dot(.) operator along with the module name.
If you have a look at the Python standard lib, you see that all three of them are used:
subprocess
uses solutions 1 and 2; there are several places where the test happens.
os
uses a variant of solution 3 (import ... as path
).
So use the one which seems the most appropriate and the simplest.
[Solution 1]
how does Python behave (internally) if one needs to call "
from persistenv import my_function2
"?
It behaves exactly as wanted. The function which has been defined when importing the module is exported.
Technically, the module is imported just like with import module
, and then the given name is looked up in its namespace and put into the current one.
[Solution 3]
can't it be problematic when persistenv.py, persistenv_win.py and persistenv_linux.py are part of a same package (among other modules) which I would globally import by doing "import my_package" in the main script ?
Why should it be problematic? You import my_package
into the main script, and then the main script (or one module of the package) does the said import from a platform-dependent module. That is perfectly valid.
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