• 简明Python3教程 10.模块


    简介

    现在你已经知道通过定义函数可以在你的程序中复用代码。但当你想在你编写的其他程序中复用大量函数怎么办呢?

    也许你可以猜到了,办法就是利用模块。

    有各种编写模块的方式,但最简单的方式是创建一个以.py为后缀的文件并包含所需的函数与变量。

    另一种方式是以编写python解释器的本地语言编写模块。

    例如C语言编写的模块被编译后可供运行于标准python解释器上的python代码使用。

    模块可以被其它程序导入以使用其提供的功能。这也是为什么我们可以使用python标准库。

    我们先来看看如何使用标准库模块。

    范例:

    #!/usr/bin/python

    # Filename: using_sys.py

    import sys

    print('The command line arguments are:')

    for i in sys.argv:

        print(i)

    print('/n/nThe PYTHONPATH is', sys.path, '/n')

    输出:

        $ python using_sys.py we are arguments

        The command line arguments are:

        using_sys.py

        we

        are

        arguments

       

        The PYTHONPATH is ['', 'C://Windows//system32//python30.zip',

        'C://Python30//DLLs', 'C://Python30//lib',

        'C://Python30//lib//plat-win', 'C://Python30',

        'C://Python30//lib//site-packages']

    工作流程:

    首先我们使用import语句导入sys模块。本质上这告诉python我们希望使用这个模块。

    sys模块包含python解释器与其工作环境(即系统)相关的功能。

    当python执行import sys语句时,它将查找sys模块。本例中sys是内建模块之一,因此python知道在哪能找到它。

    如果导入的不是一个编译模块,即不是用python编写的模块,python解释器会在变量sys.path中列出的目录中查找它。

    (注:if it was not a compiled module i.e. a module written in Python)

    如果模块被找到,这个模块中的语句将被执行然后你就可以使用它了(注: 只有顶级语句才会执行,也就是主块中的语句)。

    注意一个模块只有在第一次导入时会被初始化。

    sys模块中的argv通过点号引用即sys.argv。它清晰的指出这个名字是sys模块中的一部分。

    这种语法的另一个优势是不会和你的程序中的同名argv变量发生冲突。

    变量sys.argv是一个字符串列表(后章会详细解释列表)。

    具体说sys.argv是一个包含命令行参数的列表,也就是使用命令行传递给你的程序的参数。

    如果你在使用IDE编写程序,请在菜单中查找为程序指定命令行参数的方法。

    这里,当我们执行python using_sys.py we are arguments时,我们以python命令运行using_sys.py模块,其后的内容是传递给程序的参数。

    python将它们存到sys.argv以供我们使用。

    记住,被运行脚本的脚本名永远是sys.argv的第一个参数。

    所以本例中sys.argv[0]’using_sys.py’sys.argv[1]’we’sys.argv[2]’are’, argv[3]’arguments’。注意python下标从0开始而非1

    sys.path包含一个目录名列表指示从哪里导入模块。

    观察程序输出,sys.path的第一个字符串为空 – 其指出当前目录也是sys.path的一部分,这与PYTHONPATH环境变量是相同的。

    这意味着你可以直接导入当前目录下的模块,否则你就必须将你的模块放到sys.path列出的目录中的一个了。

    注意程序在哪个目录运行的,这个目录就是这个程序的当前目录。运行import os; print(os.getcwd()) 可以看到你的程序的当前目录。

    (注:windows下sys.path[0]可能不为空,而是显式指出当前路径)

    字节编译文件 .pyc

    导入模块是一个相对昂贵的操作,所以python使用了一些技巧加速这个过程。

    一个办法是创建后缀为.pyc的字节编译文件用于将程序转换为中间格式。(还记得介绍python如何工作的那一节吗?)

    当你下次从其他文件导入模块时pyc文件会非常有用 – 它将大大增加导入速度,因为导入模块的部分操作已经预先完成了。

    并且这个字节编译文件仍然是平台无关的。

    注意

    .pyc文件一般被创建在与其对应的.py文件所在的相同目录下。如果python没有这个目录的写权限,则.pyc文件不会被创建。

    from…import…语句

    如果你希望将变量argv直接导入到你的程序中(避免每次输入sys.),那么可以使用from sys import argv语句。

    如果希望导入sys模块中的所有名字,则from sys import *可以做到。此语句可以用于任何模块。

    通常你应该避免使用这个语句并用import语句代替之,因为使用后者可以避免名字冲突,程序的可读性也更好。

    模块的__name__属性

    每个模块都有一个名字,并且通过模块中的某些语句可以得到这个模块名。

    在一些想要搞清模块是独立运行还是被导入的情况下,这会非常方便。

    如前所述当模块第一次被导入时模块中的代码会被执行。我们可以据此改变模块独立执行时的行为方式。

    这可以通过模块的__name__属性做到。(注:独立运行是指程序最开始运行的那个脚本文件(/模块))

    范例:

    #!/usr/bin/python

    # Filename: using_name.py

    if __name__ == '__main__':

        print('This program is being run by itself')

    else:

        print('I am being imported from another module')

    输出:

        $ python using_name.py

        This program is being run by itself

       

        $ python

        >>> import using_name

        I am being imported from another module

        >>>

    工作流程:

    每个python模块都有自己的__name__定义,如果它是’__main__’则暗示模块为独立运行,我们可以进行一些适当的处理。

    制作你自己的模块

    创建你自己的模块很简单,其实你一直在这样做!因为每个python脚本都是一个模块。你只需确保它带有.py扩展名即可。

    下面的例子会让你对其有一个清晰的认识:

    范例:

    #!/usr/bin/python

    # Filename: mymodule.py

    def sayhi():

        print('Hi, this is mymodule speaking.')

    __version__ = '0.1'

    # 结束mymodule.py编写

    上面就是一个简单的模块,如你所见,这和我们平时的python程序相比没有什么特别之处。

    记住模块应该放到导入它的那个程序所在的目录下,或者放到sys.path列出的目录之一中。

    #!/usr/bin/python

    # Filename: mymodule_demo.py

    import mymodule

    mymodule.sayhi()

    print ('Version', mymodule.__version__)

    输出:

        $ python mymodule_demo.py

        Hi, this is mymodule speaking.

        Version 0.1

    如何工作:

    注意我们同样使用点号访问模块成员。

    python很好的重复利用了相同的符号,带来独特的’Pythonic’感受,这样我们就不必学习更多的语法知识了。

    下面是一个使用from…import语法的版本:

    #!/usr/bin/python

    # Filename: mymodule_demo2.py

    from mymodule import sayhi, __version__

    sayhi()

    print('Version', __version__)Python en:Modules 59

    mymodule_demo2.pymymodule_demo的输出完全相同。

    注意,如果导入mymodule的模块中已经存在同名的__version__,则将发生名字冲突。

    事实上这很可能发生,因为每个模块都用__version__声明它的版本是一种常见的做法。

    因此建议你优先考虑import语句,虽然它可能会让你的程序变的更长一些。

    你同样可以使用:

    from mymodule import *

    这将导入模块的所有公有名字,例如sayhi,但是不会导入__version__因为它以双下划线开头。

    Python之禅

    python的一个指导原则是”清晰的好过隐晦的”. 执行import this可以看到完整内容。

    这里的讨论列出了每个原则的范例(http://stackoverflow.com/questions/228181/zen-of-python)

    dir函数

    你可以使用dir函数列出一个对象定义的所有标识符。例如对于一个模块,标识符包括函数,类,变量。

    当你为dir()函数提供一个模块名,它将返回定义在其中的所有名字。

    dir()的参数为空时,返回定义在当前模块中所有名字。

    范例:

    $ python

    >>> import sys # 得到sys模块的属性列表

    >>> dir(sys)

    ['__displayhook__', '__doc__', '__excepthook__', '__name__',

    '__package__', '__stderr__', '__stdin__', '__stdout__', '_clear_type_cache',

    '_compact_freelists', '_current_frames', '_getframe', 'api_version', 'argv',

    'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook',

    'dllhandle', 'dont_write_bytecode', 'exc_info', 'excepthook', 'exec_prefix', executable',

    'exit', 'flags', 'float_info', 'getcheckinterval', 'getdefaultencoding', 'getfil

    esystemencoding', 'getprofile', 'getrecursionlimit', 'getrefcount', 'getsizeof',

    'gettrace', 'getwindowsversion', 'hexversion', 'intern', 'maxsize', 'maxunicode',

    'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform',

    'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setprofile', 'setrecursionlimit',

    'settrace', 'stderr', 'stdin', 'stdout', 'subversion', 'version', 'version_info', 'warnoptions', 'winver']

    >>> dir() # 得到当前模块的属性列表

    ['__builtins__', '__doc__', '__name__', '__package__', 'sys']

    >>> a = 5 # create a new variable 'a'

    >>> dir()

    ['__builtins__', '__doc__', '__name__', '__package__', 'a', 'sys']

    >>> del a # 删除名字a

    >>> dir()

    ['__builtins__', '__doc__', '__name__', '__package__', 'sys']

    工作流程:

    首先,我们通过被导入的sys模块应用dir函数. 可以看到sys包含巨多的属性。

    接下来,我们不为dir函数提供参数。默认的它返回当前模块的属性列表。注意被导入模块列表也是当前模块列表的一部分。

    为了观察到dir确定起作用了,我们定义一个新变量a并为其赋值然后检验dir的返回值,我们发现在返回的列表中确实出现

    了一个与变量a同名的值。在我们使用del语句删除当前模块的变量/属性后,改变再次反映到了dir函数的输出上。

    del注解 – 这个语句用于删除一个变量/名字,在本例中,del a之后你就无法访问变量a了 – 就像它从来没有存在过一样。

    注意dir()函数可用于任何对象。例如执行dir (print)学习更多关于print函数的属性,或是dir(str)列出str类的属性。

    如今,你必须开始留心组织你的程序层次了。

    变量在函数内部,函数和全局变量通常在模块内部。那么如何组织模块呢?这就轮到登场了。

    仅仅是包含模块的文件夹,并带有一个特殊的文件__init__.py用于指示python这个文件夹是特殊的,因为它包含python模块。

    让我们假设你需要创建一个叫做’world’的包,里面包括诸如’asia’‘africa’等的子包。

    下面告诉你应该如何组织文件夹结构:

        - <some folder present in the sys.path>/

            - world/

                - __init__.py

                - asia/

                    - __init__.py

                    - india/

                        - __init__.py

                        - foo.py

                - africa/

                    - __init__.py

                    - madagascar/

                        - __init__.py

                        - bar.py

    包只是用来有层次的组织模块。你会在标准库中看到它的很多应用。

    小结

    就象函数是程序的可复用部分一样,模块是可复用的程序。

    包用于组织模块的层次结构。python自带的标准库正是一组包和模块的范例。

    我们已经看到如何使用这些模块,并且知道如何创建自己的模块。

    接下来,我们将学习一个比较有趣的概念 – 数据结构。

  • 相关阅读:
    JDBC(5)-处理大数据
    JDBC(4)-Result结果集
    JDBC(3)-使用PreparedStatement接口实现增、删、改操作
    JDBC(2)-使用statment接口实现增删改操作
    JDBC(1)-连接数据库
    selenium+junit4实现参数化自动化测试
    selenium自动化测试用例需要关注的几点(二)
    【转】selenium自动化测试用例需要关注的几点(一)
    Selenium+excel实现参数化自动化测试
    POI基本操作
  • 原文地址:https://www.cnblogs.com/lanzhi/p/6468007.html
Copyright © 2020-2023  润新知