1

Is it possible to achieve this in python? Basically, shared_fun() is a very frequently used utility function, used in multiple modules (user_module1 and user_module2). However, each user wants a slightly different parameter SHARE_GLOBAL_VAR.

Some motivation why I would want it this way:

A. Imagine there are a lot of shared_fun(), shared_fun1(), shared_fun2() ...... and all of them rely on the same SHARE_GLOBAL_VAR but do different things with it. Therefore I really don't want to make SHARE_GLOBAL_VAR an argument for every one of those shared_fun(SHARE_GLOBAL_VAR)

B. I want to make the maintenance of shared_fun() easy so that I don't want to copy the code into each user_module.py file individually.

I think the task boils down to make a copy of share module namespace inside each user_module namespace, which I'm not sure if it's legal in python.

#share.py:
SHARE_GLOBAL_VAR = 0
def shared_fun():
    return SHARE_GLOBAL_VAR

#user_module1.py:
import share
share.SHARE_GLOBAL_VAR = 1
def user1_fun():
    return share.shared_fun()

#user_module2.py:
import share
share.SHARE_GLOBAL_VAR = 2
def user2_fun():
    return share.shared_fun()

#main.py:
import user_module1
import user_module2
# expecting a result of 1
print(user_module1.user1_fun())
# expecting a result of 2
print(user_module2.user2_fun())
Shichu Zhu
  • 311
  • 3
  • 15
  • Isn't using the same function with different parameter simpler than using different function? If you reaaaally want to, you can just move assignment inside functions. – Sraw Nov 28 '17 at 06:26
  • 1. It's worth thinking if an identical value needs to be passed to every shared_fun function. 2. if assigning the value inside function, the performance will be bad if the two functions user_module1/2.user1/2_fun() are called alternatively frequently (a lot of switching overhead). The goal is to create multiple copies of function without need to write duplicate code. The OOP or the closure method actually illustrate and solve both concerns. – Shichu Zhu Nov 28 '17 at 08:24

4 Answers4

1

You can make use of the concept of closure , for example

def sharedFun():
    shared_var=0
    def getSharedVariable(shared_value=None):
        if shared_value:
            return shared_value
        else:
            return shared_var
    return getSharedVariable


shared=sharedFun()
print shared(1) # output 1
print shared(2) # output 2
print shared(3) # output 3
print shared() # output 0

you can find more about closure here

pushpendra chauhan
  • 2,205
  • 3
  • 20
  • 29
1

Claim down guy. Let me explain step by step for you.

First, take a careful look at your accepted answer. Actually, there is no essential difference between this answer and a modified version of your original question.

#share.py:
SHARE_GLOBAL_VAR = 0
def getSharedVariable(shared_value=None):
    if shared_value:
        return shared_value
    else:
        return SHARE_GLOBAL_VAR

In accepted answer, the scope is function sharedFun while the scope is module in the above snippet. There are almost the same. You can use the above snippet like this:

import share
shared = share.getSharedVariable
print shared(1) # output 1
print shared(2) # output 2
print shared(3) # output 3
print shared() # output 0

You are still passing an identical value to getSharedVariable.

Further, let's talk about your OOP solution. It is just meaningless. If each object will have their own different SHARE_GLOBAL_VAR, why this variable called SHARE_GLOBAL_VAR? It is just a normal local variable.

Finally, let's modify the accepted answer:

# assume SHARE_GLOBAL_VAR equals to 0.
def getSharedVariable(shared_value=SHARE_GLOBAL_VAR):
    return shared_value

shared = getSharedVariable
print shared(1) # output 1
print shared(2) # output 2
print shared(3) # output 3
print shared() # output 0

Do you notice what you are actually want? Just a default parameter.

Sraw
  • 18,892
  • 11
  • 54
  • 87
  • Thanks for your explanation, Sraw! Been calming down for a few days while getting exposed to more closure and decorators, I adore the accepted answer because I appreciate its powerfulness and the fact it does solve the problem. You answer certainly will work as well. However, in the share.py module, there are actually a lot more functions acting similarly with SHARE_GLOBAL_VAR. I admit this is a bad naming since it's really a module-level constant and shouldn't be accessed directly in the main.py, let rename it to SHARE_CONST_VAR. – Shichu Zhu Dec 02 '17 at 02:13
  • And the same idea applies to both user_module1.py and user_module2.py, in that there are a lot similar function based on shared.SHARE_CONST_VAR. I need certain data encapsulation while keeping each user_module.py having its own distinct SHARE_CONST_VAR. That's the main reason I'm reluctant to make it a parameter with a default value in every single function in user_module.py. To achieve this, and given that there's only one shared.SHARE_CONST_VAR existing in the entire program, I have to create multiple versions of functions in the different user_module.py. – Shichu Zhu Dec 02 '17 at 02:14
  • And this can be achieved by either user OOP, or as advocated by the accepted answer using closure. – Shichu Zhu Dec 02 '17 at 02:14
0

For a given file on disk, there is at most one in-memory module object per process, so what you show above, with multiple imports in one process, will not work. This is why it is 'impolite' for 3rd party library modules to 'monkey patch' standard library modules and why global data variables are generally discouraged.

Terry Jan Reedy
  • 18,414
  • 3
  • 40
  • 52
0

pushpendra's answer of closure is fantastic!!! I know very little about functional programming but this is really inspiring me to dig more into it.

On the other hand, I just came up with an OOP solution for my specific issue: make the shared.py a class and all the shared_fun as class method while SHARE_GLOBAL_VAR is now a class data member. Each user_module1/2 will now just instantiate an object of the share class with different SHARE_GLOBAL_VAR.

This achieves the similar idea of creating multiple copies of share_fun, via a class instead of duplicating module importing (which is impossible per Terry's answer).

My very naive comparison between OOP and Functional in this case: Closure solution provides much more freedom in creating different versions of functions. Since closure provides function duplicate per function instead of per GLOBAL_SHARE_VAR, therefore it saves the overhead of creating unnecessary methods that are never used by the OOP solution.

Time to get serious about functional programming!

Shichu Zhu
  • 311
  • 3
  • 15