How to import a python file to multiple files of a module with them not using the same variables?

177 Views Asked by At

I have a python file, let's say it is common.py

In this, I have some functions, and a variable which is needed for the functions:

TAG = '[TESTTAG]'

def myprint(obj):
    print(f'{TAG} {obj}')

def set_tag(out_tag):
    global TAG
    TAG = out_tag

I want to be able to use the myprint() function without having to pass the TAG parameter each time. To set this TAG, I coded the set_tag() function

I have 2 other files, where I want to use the myprint() function, but with different tags: use1.py

from common import *

set_tag('[USE1TAG]')

def testusage():
    myprint('First sentence')
    myprint('Second sentence')

if __name__ == '__main__':
    testusage()

use2.py

from common import *
set_tag('[USE2TAG]')

def testusage2():
    myprint('Third sentence')
    myprint('Fourth sentence')


if __name__ == '__main__':
    testusage2()

When I run them individually, they produce the expected result.

But the problem is that I want to import both these files to a final file, and use their functions multiple times, with each using the TAG, that I previously set in their source files. This way the latest imported file changes the TAG to [USE2TAG], and that will remain used.

combine.py

from use1 import testusage
from use2 import testusage2

if __name__ == '__main__':
    testusage()
    testusage2()
    testusage()
    testusage2()

Output:

[USE2TAG] First sentence
[USE2TAG] Second sentence
[USE2TAG] Third sentence
[USE2TAG] Fourth sentence
[USE2TAG] First sentence
[USE2TAG] Second sentence
[USE2TAG] Third sentence
[USE2TAG] Fourth sentence

Expected result:

[USE1TAG] First sentence
[USE1TAG] Second sentence
[USE2TAG] Third sentence
[USE2TAG] Fourth sentence
[USE1TAG] First sentence
[USE1TAG] Second sentence
[USE2TAG] Third sentence
[USE2TAG] Fourth sentence

The problem is that they operate on the same TAG variable. I know, that I could pass the TAG to the myprint() function each time, but I think that there must be a way to not use that.

I know that I could define the myprint() function to both the use1.py and the use2.py, but I would rather just import it as a "service", so I don't have to append it each time.

Is there a way to use the myprint() function in multiple files without passing the TAG parameter?

Thanks for the answers!

2

There are 2 best solutions below

1
On BEST ANSWER

One way to achieve this would be to have a function that returns a correctly configured print function that you could then use. For this you could use a lambda. For example:

def _myprint(tag, obj):
    print(f'[{tag}] {obj}')

def get_myprint(tag):
    return lambda obj, tag=tag: _myprint(tag, obj)

And then where it's being used you can do something like:

print_a = get_myprint('a')
print_b = get_myprint('b')

print_a('test a')
print_b('test b')

Which gives

[a] test a
[b] test b
1
On

You should check out functools.partial, which is super helpful for this kind of thing. In the file where you define myprint, have a generic function defined:

def generic_myprint(tag, obj):
    print(f'{TAG} {obj}')

Then, in the files where you're importing myprint, have the following code:

from functools import partial
from common import generic_myprint
myprint = partial(generic_myprint, tag='[USE1TAG]')

Obviously, replace the tag argument for each file where you want a different value.

functools.partial takes a function with many arguments, and returns a new partial object, which behaves exactly the same way as the original function, but with one or more parameters "pre-loaded" as default values. In this case, myprint now needs only the obj parameter when called. generic_myprint accepted 2 arguments, but myprint only accepts 1.

In my opinion, this is more pythonic than using a lambda function, but your mileage may vary!

https://docs.python.org/3/library/functools.html