Some confusion regarding import in Python

I am new to Python and there is something that has been bothering me for quite some time. I read in “Learning Python” by Mark Lutz that when we use the from operator to import a name that is present in a module, it first imports the module and then assigns it a new name (that is, the name of the function, class, etc. present in the imported module), and then deletes the module object using the del operator. However, what happens if I try to import the name using from , which refers to the name in the imported module, which itself is not imported? Consider the following example, in which there are two modules, mod1.py and mod2.py :

 #mod1.py from mod2 import test test('mod1.py') #mod2.py def countLines(name): print len(open(name).readlines()) def countChars(name): print len(open(name).read()) def test(name): print 'loading...' countLines(name) countChars(name) print '-'*10 

Now let's see what happens when I run or import mod1:

 >>>import mod1 loading... 3 44 ---------- 

Here, when I imported and ran the test function, it worked successfully, although I didn’t even import countChars or countLines , and the from statement already deleted the mod2 module mod2 .

Therefore, I basically need to know why this code works, although taking into account the problems that I talked about, this should not be.

EDIT: Thanx a lot to everyone who answered :)

+6
source share
6 answers

I think you're struggling with how python handles namespaces . when you enter from module import thing you transfer thing from module to the current namespace. So, in your example, when mod1 imported, the code is evaluated in the following order:

 from mod2 import test #Import mod2, bring test function into current module namespace test("mod1.py") #run the test function (defined in mod2) 

And now for mod2:

 #create a new function named 'test' in the current (mod2) namespace #the first time this module is imported. Note that this function has #access to the entire namespace where it is defined (mod2). def test(name): print 'loading...' countLines(name) countChars(name) print '-'*10 

The reason this is important is because python allows you to choose exactly what you want to insert into your namespace. For example, let's say you have module1 , which defines the cool_func function. Now you are writing another module ( module2 ), and it makes it so that module2 also exists for cool_func . Python allows you to save them separately. In module3 you can do:

 import module1 import module2 module1.cool_func() module2.cool_func() 

Or you could do:

 from module1 import cool_func import module2 cool_func() #module1 module2.cool_func() 

or you could do:

 from module1 import cool_func as cool from module2 import cool_func as cooler cool() #module1 cooler() #module2 

Opportunities go on ...

I hope my point is clear. When you import an object from a module, you choose how you want to reference this object in the current namespace.

+4
source

Each function has an __globals__ attribute, which contains a link for the environment in which it searches for global variables and functions.

Then the test function is associated with the global variables mod2 . Therefore, when it calls countLines , the interpreter will always find the desired function, even if you wrote a new one with the same name in the module importing the function.

+6
source

Other answers are better formulated than this, but if you run the following, you will see that countChars and countLines are actually both defined in test.__globals__ :

 from pprint import pprint from mod2 import test pprint(test.__globals___) test('mod1') 

You can see that the test import combines the other global variables defined in mod2 , allowing you to run the function without worrying about importing everything you need.

+3
source

Each module has its own area. Within mod1 you cannot use the names countLines or countChars (or mod2 ).

mod2 itself does not in any way affect how this happens elsewhere; all names defined in it are available in the module.

If the webpage you are linking to really says that the module object has been deleted using the del statement, that’s wrong. del deletes only names, does not delete objects.

+1
source

The import statement loads the entire module into memory, so the test() function worked successfully.

But since you used the from operator, why can't you use countLines and countChars , but test can call them.

Operator

from loads the entire module and sets the imported function, variable, etc. into the global namespace.

eg,

 >>> from math import sin >>> sin(90) #now sin() is a global variable in the module and can be accesed directly 0.89399666360055785 >>> math Traceback (most recent call last): File "<pyshell#2>", line 1, in <module> math NameError: name 'math' is not defined >>> vars() #shows the current namespace, and there sin() in it {'__builtins__': <module '__builtin__' (built-in)>, '__file__': '/usr/bin/idle', '__package__': None, '__name__': '__main__', 'main': <function main at 0xb6ac702c>, 'sin': <built-in function sin>, '__doc__': None} 

consider a simple file, file.py:

 def f1(): print 2+2 def f2(): f1() 

import only f2:

 >>> from file import f2 >>> f2() 4 

although I only imported f2() not f1() , but it successfully executed f1() because the module is loaded into memory, but we can only access f2() , but f2() can access other parts of the module.

+1
source

FROM THE PITON APPOINTMENT GUIDE ,

Although modules have their own global namespaces, this does not mean that all names can be used throughout the module. Scope refers to the scope of the program from which the namespace without prefix is ​​available. Areas are important for the insulation that they provide in the module. At any time, several areas are involved in the work: the scope of the current function, the scope of the module, and then the scope of the built-in Python. This nesting of scopes means that one function cannot access names inside another function.

Namespaces also look inside out. This means that if a specific name is specified in the global module namespace, you can reuse the name inside the function, being sure that any other function will receive a global name. Of course, you can force the function to use the global name, the prefix name with the global keyword. But if you need to use this, then you might be better off using classes and objects.

+1
source

Source: https://habr.com/ru/post/922872/


All Articles