I recently learned of the __ import__ function and found that I could store a module in a variable, so I was thinking of making a list of modules and then calling the appropriate one when necessary.
So I might have three modules test1, test2, test3, each containing a single function "print_hello" that simply prints "hello, I'm [module name]"
At runtime, I would call some function to import those modules and put them in a list.
Then I would pick a random number between 0 and 2 inclusively, pick that module from the list, and print hello.
#run function to import each module, resulting in the following list
#my_modules = [module1, module2, module3]
#generate some number i
chosen_module = my_modules[i]
chosen_module.print_hello()
Is this acceptable coding practice? Or are there any reasons that would discourage this?
I use this sort of approach in some of my testing code. I want to test output from one version of a module against a different versions of the same module. Being able to iterate over different module instances makes the code cleaner.
But this sort of code is the exception to the rule. It's very infrequently that this approach is the cleanest solution to a problem.
Related
Case I: In some cases, I use the library name to call some set of function i.e, np.median().
Case II: And in some cases, I use the variable name and library name to call another set of function i.e, np.mean(heights) or heights.mean().
In case II, I am able to use both library name and variable name. In case I, only library name works.
My doubt is how to differentiate these tow sets of functions.
If I am wrong in anyway, please clear my thoughts.
(here i am referring to python language)
thank you.
In the first case you’re calling a method (function) of the library. Libraries are usually class instances or collections of functions within a module.
In the second example instead, you’re again calling a function from the module but in this case it returns a ndarray (a numpy list basically) which itself has some methods that can be called on it.
Scenario
Let test be the module we run as __main__. This module contains one global variable named primes, which is initialized in the module with the following assignment.
primes = []
The module also contains a function named pi, which alters this global variable:
def pi(n):
global primes
"""Some code that modifies the global 'primes' variable"""
I then want to time said function using the builtin timeit module. I want to use the timeit.repeat function and get the minimum value of the timing, as a way of improving the measurement's accuracy (instead of measuring just one time, which may be subject to slow-down due to unrelated processes).
print(min(timeit.repeat('test.pi(50000)',
setup="import test",
number=1, repeat=10)) * 1000)
The problem is that the pi function behaves differently depending on the value of primes: I expected that, for each repetition, the import test statement in the setup parameter would re-run the primes = [] statement in the test, thus 'resetting' primes so that the code being executed would be identical for each repetition. But, instead, the value of primes that resulted from the previous execution is used, so I had to add the statement test.primes = [] to the setup parameter:
print(min(timeit.repeat('test.pi(50000)',
setup="import test \n" + "test.primes = []",
number=1, repeat=10)) * 1000)
Question
This leads me to the question: is there a direct way (i.e. in one statement) to 'reset' the values of all the global variables to what they were when they were first assigned in the module?
In this specific scenario adding that one statement to manually 'reset' primes works fine, but consider a case in which there are a lot of global variables, and you want to 'reset' all of them.
Side quest-ion
Why doesn't the statement import test re-run the initial primes = [] assignment?
Let's start with your side question, because it turns out that it's actually central to everything:
Why doesn't the statement import test re-run the initial primes = [] assignment?"
Because, as explained in the docs on the import system and the import statement, what import test does is, loosely, this pseudocode:
if 'test' not in sys.modules:
find, load (compiling if needed), and exec the module
sys.modules['test'] = result
test = sys['test.modules']
OK, but why does it do that?
If you have two modules that both import the same module, they expect to see the same globals. And remember that types, functions, etc. defined at the top level of a function are all globals. For example, if sortedlist.py imports collections.abc to class SortedList(collections.abc.Sequence):, and scraper.py imports collections.abc to isinstance(something, collections.abc.Sequence), you'd want a SortedList to pass that test—but it won't if those are two completely independent types because they came from two different module objects that happen to have the same name,
If you have 12 modules that all import pandas as pd, you'd be running all the Pandas initialization code 12 times. Except that some of your modules also probably import each other, so they'd each be run multiple times, and import Pandas each time. How long do you think it would take to run all the Pandas initialization 60 times?
So, reusing existing modules is almost always what you want.
And when you don't, that's usually a sign that there's something wrong with your design (which may well be the case here).
But "almost always" isn't "always". So there are ways around it. None of them are usually a good idea for live code, but for things like unit tests and benchmarking, there are three basic options that are all fine, as long as the tradeoffs are the ones you want:
del sys.modules['test']. This is obviously pretty hacky, but it actually does exactly what you want here. Any existing references to the old module are completely untouched, but the next time anyone does import test, they're going to get a brand-new test module.
importlib.reload(test). This sounds great, but it may on the one hand be overkill (notice that it forces the module source to be recompiled, which you don't need), while on the other it may not be sufficient (it doesn't actually reset the globals—if your code does primes = [] at the top level, that line gets executed, so who cares, but if your code instead does, say, globals().setdefault('primes', []) inside the pi function, you care).
Instead of import test, manually do all the steps up through executing the module (see the examples in the importlib docs), but don't store it in sys.modules['test'] or in test, just store it in a local variable you discard after each test. This is probably the cleanest, although it does mean 6 lines of code instead of 1.
This question already has answers here:
Understanding the dot notation in python
(2 answers)
Closed 5 years ago.
I am struggling to explain the use of the dot. I thought it might be another way of multiplying variables but get an error when I try run such a code.
I can't explain what it is doing exactly, take this code for example:
import random
for i in range(100):
value = random.randint(1, 10)
print(value)
I understand what the code does but in line 3 I am confused by random.randint what is the dot doing here? randint is not defined or imported so how does the program know what is being asked of it?
An brief explanation of the above code would be nice but a good explanation of the use of the dot in python would be appreciated.
You use dot for 3 main reasons:
Accessing members of a module: a module is simply a python file, and members can be variables, functions, classes and so on.
Accessing modules within a package: a package is a directory containing a__init__ module. Some packages are nested and contain inner packages. You have to reach the innermost and then the module. For both you use dot syntax.
And at last, accessing members of a class, for example method (functions) fields (variables) and so on.
In your above code random is a Python module and you are accessing its function randint.
In Python, the dot operator is used to access attributes of objects.
In your example, think of the module imported "random" as an object which has various functions like randint, shuffle, etc
So, when you say "random.randint()", you are accessing the function "randint" from the module "random"
The dot here is used to resolve scope. The randint() function is inside the random module. The dot here tells the interpreter where to look for the named function/ data member.
Apart from this, the dot is also used to access functions and data members from an object reference.
For example:
op = object.function()
Here, the function() is being accessed using the reference of object.
Also you can access inner modules using . like this:
import module.submodule
More information here: https://www.codecademy.com/en/forum_questions/5170307264a7402d9a0012f5
random is a package and randint() is its method. Dot notation here works just like it does in any other language. It's used to access the
randint property of random module.
Is there a way to get the dictionary containing the global variables in a specific module namespace? It looks that you can achieve it if the module contains at least one function with something like:
import mymodule
d = mymodule.func.__globals__
Is this right?
Is there a more general way? (For instance, how could this be done if the module wouldn't contain any function but only variables?)
I am not expecting a "What are you trying to do with that? There is probably another way of doing it." answer; my question is rather a theoretical one.
I am more interested here by a Python3 answer if it matters.
Just grab use vars which grabs its __dict__ which corresponds to the global scope.
vars(mymodule)
func.__globals__ simply returns this dictionary for you see how:
vars(mymodule) is mymodule.func.__globals__
returns True.
I have two functions like the following:
def fitnesscompare(x, y):
if x.fitness>y.fitness:
return 1
elif x.fitness==y.fitness:
return 0
else: #x.fitness<y.fitness
return -1
that are used with 'sort' to sort on different attributes of class instances.
These are used from within other functions and methods in the program.
Can I make them visible everywhere rather than having to pass them to each object in which they are used?
Thanks
The best approach (to get the visibility you ask about) is to put this def statement in a module (say fit.py), import fit from any other module that needs access to items defined in this one, and use fit.fitnesscompare in any of those modules as needed.
What you ask, and what you really need, may actually be different...:
as I explained in another post earlier today, custom comparison functions are not the best way to customize sorting in Python (which is why in Python 3 they're not even allowed any more): rather, a custom key-extraction function will serve you much better (future-proof, more general, faster). I.e., instead of calling, say
somelist.sort(cmp=fit.fitnesscompare)
call
somelist.sort(key=fit.fitnessextract)
where
def fitnessextract(x):
return x.fitness
or, for really blazing speed,
import operator
somelist.sort(key=operator.attrgetter('fitness'))
Defining a function with def makes that function available within whatever scope you've defined it in. At module level, using def will make that function available to any other function inside that module.
Can you perhaps post an example of what is not working for you? The code you've posted appears to be unrelated to your actual problem.