Why is the behavior different from global variables in the "import module" and "from the import module"?

Let a.py :

def foo(): global spam spam = 42 return 'this' 

On the console, if I just import a , I understand everything:

 >>> import a >>> a.foo() 'this' >>> a.spam 42 

However, if I do a less popular thing and ...

 >>> from a import * >>> foo() 'this' >>> spam Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'spam' is not defined >>> a.spam Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'a' is not defined 

I read opinions about why people don't like β€œ from module import * ” in terms of namespace, but I can’t find anything about this, and to be honest, I realized that this is the problem that I ran into an accident.

+7
python
source share
3 answers

When you request a.spam , the namespace in the a and spam module is searched. But when you ask for just spam :

 >>> from a import * # imported foo, spam doesn't exist yet >>> foo() 

spam is created in the namespace a (you cannot access it with such an import, though), but not in the current module. And it seems that no one promised to add the newly added global values a to the entire module namespaces a was imported via * . This will require storing import links inside the interpreter and will probably lead to performance degradation if one heavily imported module performs such tricks all the time.

And imagine that you defined spam in your main module before calling foo() . That would be a direct clash of names.

As an illustration, you can do from a import * to get the latest updates for module a :

 from a import * print(foo()) from a import * print(spam) 
+9
source share

Step by step:

At the time of import, a has only the symbol foo , which refers to the function.

Only if the function is executed, a gets the extra spam character.

In the first case, you execute import a and get a β€œhandle” to the module, which allows you to keep track of what happens later. If you do a.spam before calling a.foo() , you get an error.

In the second case, from a import * gives you everything that is currently in the module, and this is just spam() . After that, you can do from a import * to get spam .

+2
source share

I generally agree with Vovanrock2002.

As I was recently explained, "." is an area resolution operator. import a and from a import * give you different syntaxes. from a import * separately imports each global variable from a and binds them as variables in the local scope. A more practical example might be the difference between import datetime and from datetime import date . With the first, I have to create a date object using datetime.date(2015, 11, 12) , and the last I just use date(2015, 11, 12) .

You can read more about the import statement

Nevertheless, I should have been different from you in that I do not think that spam is the meaning of life, the universe and everything.
+1
source share

All Articles