美文网首页工作生活
Python 模块与包的导入问题

Python 模块与包的导入问题

作者: Dozing | 来源:发表于2019-07-03 19:26 被阅读0次

    Python模块(Module)

    • Python模块,是一个python文件。以.py结尾。包含了Python对象定义和Python语句。

    • 模块能定义函数,类和变量。模块里也能包含可执行的代码。这些语句用于初始化模块

    • 模块中的定义可以导入到其他模块或者住模块。习惯上但不要求把所有import语句放在模块(或脚本)的开头。被导入的模块名存放在调入模块的全局符号表中

    • 每个模块都有自己的私有符号表,该表用作模块中定义的所有函数的全局符号表。因此模块的作者可以在模块内使用全局变量,而不必担心与用户的全局变量发生意外冲突。

    下例子是Python官网上面的模块fibo.py

    # Fibonacci numbers module
    
    def fib(n):    # write Fibonacci series up to n
        a, b = 0, 1
        while a < n:
            print(a, end=' ')
            a, b = b, a+b
        print()
    
    def fib2(n):   # return Fibonacci series up to n
        result = []
        a, b = 0, 1
        while a < n:
            result.append(a)
            a, b = b, a+b
        return result
    
    

    模块定义好后,我们可以使用import语句来引入模块

    import module[,module2[,....module]]
    

    例如要引用模块math,就可以在文件最开始的地方用import math来引入。调用math模块中的函数时,必须这样引用:模块名.函数名

    导入模块中函数的方法

    • 方法一:import 函数名
      使用时: 模块名.函数名()

    • 方法二:from 模块名 import 函数名
      使用时: 函数名()
      例子

    >>> from fibo import fib, fib2
    >>> fib(500)
    0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
    
    • 方法三:from 模块名 import *
      使用时: 函数名()
      例子:
    >>> from fibo import *
    >>> fib(500)
    0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
    

    这会调入所有非以下划线(_)开头的名称。在多数情况下,Python程序员都不会使用这个功能,因为它在解释器中引入了一组未知的名称,而它们很可能会覆盖一些你已经定义过的东西。
    注意通常情况下从一个模块或者包内调入*的做法是不太被接受的,因为这通常会导致代码的可读性很差。不过,在交互式编译器中为了节省打字可以这么用。

    注:在模块当中定义一个变量__all__:
    使用__all__的影响: 使用from 模块名 import *方式导入时只会导入
    __all__列表[]里面函数名。 __all__如果没有这个变量将全部导入(__all__仅限 于from 模块名 import *这种导入方式)

    例子:
    加入__all__示例:

     __all__ = ["demo"]
     def demo():
    
         print("demo")
    
     def demo1():
         print("demo1")
    

    运行结果:

    >>> from TT import *
     
    >>>demo()
    demo
     
    >>>demo1()
    -----------------------------------------------------------------------
    NameError                             Traceback (most recent call last)
    <ipython-input-3-a8330644fa2e> in <module>()
    ----> 1 demo1()
     
    NameError: name 'demo1' is not defined
    

    不加__all__示例:

    def demo():
        print("demo")
        
    def demo1():
        print("demo1")
    

    运行结果:

    >>> from TT import *
    >>> demo()
    demo
    >>> demo1()
    demo1
    
    • 方法四:from 模块名 import 函数名 as 别名
      使用时: 别名()
      例子:
    >>> import fibo as fib
    >>> fib.fib(500)
    0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
    
    >>> from fibo import fib as fibonacci
    >>> fibonacci(500)
    0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
    

    注:处于效率的考虑,每个模块在每个解释器会话中只被导入了一次。因此,如果你更改了你的模块,则必须重新启动解释器。

    以脚本的方式执行模块

    当你用下面方式运行一个Python模块:

    python fibo.py <arguments>
    

    模块里的代码会被执行,就好像你导入了模块一样,但是 __name__被赋值为 __main__。 这意味着通过在你的模块末尾添加这些代码:

    if __name__ == "__main__":
        import sys
        fib(int(sys.argv[1]))
    

    你既可以把这个文件当作脚本又可当作一个可调入的模块来使用, 因为那段解析命令行的代码只有在当模块是以main文件的方式执行的时候才会运行:

    $ python fibo.py 50
    0 1 1 2 3 5 8 13 21 34
    

    如果模块是被导入的,那些代码是不运行的:

    >>> import fibo
    >>>
    

    Python中的包

    • 包是一个分层次的文件目录结构,它定义了一个由模块及子包,和子包下的子包等组成的 Python 的应用环境。
    • 简单来说,包就是文件夹,但该文件夹下必须存在__init__.py文件, 该文件的内容可以为空。__init__.py 用于标识当前文件夹是一个包。
    • __init__.py 可以只是一个空文件,但它也可以执行包的初始化代码或设置 __all__ 变量

    下例子是Python官网上面的例子:

    sound/                          Top-level package
          __init__.py               Initialize the sound package
          formats/                  Subpackage for file format conversions
                  __init__.py
                  wavread.py
                  wavwrite.py
                  aiffread.py
                  aiffwrite.py
                  auread.py
                  auwrite.py
                  ...
          effects/                  Subpackage for sound effects
                  __init__.py
                  echo.py
                  surround.py
                  reverse.py
                  ...
          filters/                  Subpackage for filters
                  __init__.py
                  equalizer.py
                  vocoder.py
                  karaoke.py
                  ...
    

    导入包中函数,模块的方式:

    • 方法一:导入单个模块
      包的用户可以从包中导入单个模块,例如:
    import sound.effects.echo
    

    这会加载子模块 sound.effects.echo 。但引用它时必须使用它的全名。

    sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
    
    • 方法二:导入单个模块
    from sound.effects import echo
    

    这也会加载子模块 echo ,并使其在没有包前缀的情况下可用,因此可以按如下方式使用:

    echo.echofilter(input, output, delay=0.7, atten=4)
    
    • 方法三:直接导入所需的函数或变量
      另一种形式是直接导入所需的函数或变量:
    from sound.effects.echo import echofilter
    

    同样,这也会加载子模块 echo,但这会使其函数 echofilter() 直接可用:

    echofilter(input, output, delay=0.7, atten=4)
    
    • 方法四:
      from sound.effects import *

    子包参考:

    当包被构造成子包时(与示例中的 sound 包一样),你可以使用绝对导入来引用兄弟包的子模块。
    你还可以使用import语句的 from module import name 形式编写相对导入。这些导入使用前导点来指示相对导入中涉及的当前包和父包。例如,从 surround 模块,你可以使用:

    from . import echo
    from .. import formats
    from ..filters import equalizer
    

    相对导入是基于当前模块的名称进行导入的。由于主模块的名称总是 "__main__" ,因此用作Python应用程序主模块的模块必须始终使用绝对导入。

    相关文章

      网友评论

        本文标题:Python 模块与包的导入问题

        本文链接:https://www.haomeiwen.com/subject/qznqhctx.html