Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional definition of a function in a module

Tags:

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 ?

like image 246
gromk13 Avatar asked Apr 24 '13 12:04

gromk13


People also ask

What is function defined in module in Python?

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)

What are the functions of modules?

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.

How do you call a function in if condition Python?

To call a function, you have to write the function name followed by parenthesis containing the parameters you want to pass to the method.

How do you call a function from a module in Python?

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.


1 Answers

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.

like image 151
glglgl Avatar answered Nov 26 '22 04:11

glglgl