头图

In Python, we always use import to import the content of another module (file). If it is a programmer who has transferred from Java or C, there are several common pits to pay attention to:

  1. import is also an execution statement, which can be executed anywhere in the code. If we put the import in the middle of the code, the IDE is likely to have a warning, but as long as the logic is correct, ignore it:

    import a
    
    if __name__ == "__main__":
     import b
     b.methodx()

    Similar to the above code, module b is imported only when the current file is running as the main module, which not only reduces waste, but also may avoid circular references.

  2. When import is executed, if it is imported for the first time, the corresponding module will be executed once, and all top-level code in this module will be executed, so it is a very time-consuming operation, which is completely different from Java or C, which only obtains type definitions. ; So for those modules that are , try to reduce the implementation of logic in the top-level code .
  3. Even within the same module, the order of code definitions matters. The referenced code must be defined before the reference, for example:

    class A:
     x: int = 5
    
    
    class B:
     def __init__(self, y: A):
         self.y = y
    
    
    if __name__ == "__main__":
     a = A()
     b = B(a)
     print(b.y.x)
    

    In the above code, the definition of class A cannot be placed behind class B, otherwise, an error will occur at runtime, prompting name 'A' is not defined ; of course, if it is only quoted in the annotation, it can be solved by from __future__ import annotations , which is another problem.


The following content is with a , but this error is somewhat typical, it is still reserved, and it will be explained at the bottom:

  1. The namespace of import is also very important. Different namespaces will be considered as different modules. And a module, with an absolute path or a relative path, will be recognized as a different namespace , such as the following package structure:

test import

The contents of module_a are as follows:

a = {"value": 15}
print(f'a={a} in module_a')

module_b will reference module_a with an absolute path

from lang.test_import.module_a import a


a['value'] = a['value'] + 1

print(f'a={a} in module_b')

module_c1 and module_c2 import module_a with relative path and absolute path respectively, and then import module_b, you will get different results:

from module_a import a
import module_b

print(f'a={a} in module_c1')
a={'value': 15} in module_a
a={'value': 15} in module_a
a={'value': 16} in module_b
a={'value': 15} in module_c1
from lang.test_import.module_a import a
import module_b

print(f'a={a} in module_c2')
a={'value': 15} in module_a
a={'value': 16} in module_b
a={'value': 16} in module_c2

It can be seen that in module_c1, module_a has been introduced twice, which is regarded as a different module, and two variables a are also introduced, while the c1 module only recognizes a in the relative path namespace introduced by itself, so here a .value, not changed by module b.


In the above statement, the key mistake is: the absolute path under the same path is from module_a import a as a relative path, and the real relative path must be introduced with . or . file, the interpreter cannot find the root package environment, and can only treat itself as the root; and if it is used by other modules
import, the namespace will be judged based on the root of that module;

If you must run based on the main method, you can forcefully specify the owning package:

__package__ = lang.test_import
from .module_a import a
import module_b

print(f'a={a} in module_c1')

The output at this time is the same as the absolute path:

a={'value': 15} in module_a
a={'value': 16} in module_b
a={'value': 16} in module_c2

songofhawk
303 声望24 粉丝