Python入门六模块的使用
您已经了解了如何通过定义一次函数来重用程序中的代码。如果您想在您编写的其他程序中重用许多函数,该怎么办?您可能已经猜到,答案是模块。
有各种编写模块的方法,但最简单的方法是创建一个.py
包含函数和变量的扩展名的文件。
另一种方法是用编写Python解释器本身的本机语言编写模块。例如,您可以使用C编程语言编写模块,在编译时,可以在使用标准Python解释器时从Python代码中使用它们。
可以通过其他程序导入模块以利用其功能。这也是我们如何使用Python标准库的方法。首先,我们将了解如何使用标准库模块。
示例(另存为module_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 module_using_sys.py we are arguments # each arg is separated by white space
The command line arguments are:
module_using_sys.py
we
are
arguments
The PYTHONPATH is ['/tmp/py',
# many entries here, not shown here
'/Library/Python/2.7/site-packages',
'/usr/local/lib/python2.7/site-packages']
这个怎么运作
首先,我们导入了sys
使用该模块import
声明。基本上,这转化为我们告诉Python我们想要使用这个模块。该sys
模块包含与Python解释器及其环境(即系统)相关的功能。
当Python执行import sys
语句时,它会查找sys
模块。在这种情况下,它是内置模块之一,因此Python知道在哪里找到它。
如果它不是一个已编译的模块,即用Python编写的模块,那么Python解释器将在其sys.path
变量中列出的目录中搜索它。如果找到该模块,则运行该模块正文中的语句,并使模块可供您使用。请注意,初始化仅在我们第一次导入模块时完成。
使用点分表示法访问模块中的argv
变量。它清楚地表明该名称是该模块的一部分。此方法的另一个优点是名称不会与程序中使用的任何变量冲突。sys
sys.argv
sys
argv
该sys.argv
变量是一个列表字符串(列表中详细说明一个的后面的章节)。具体来说,它sys.argv
包含命令行参数列表,即使用命令行传递给程序的参数。
如果使用IDE编写和运行这些程序,请查找在菜单中为程序指定命令行参数的方法。
这里,当我们执行时python module_using_sys.py we are arguments
,我们module_using_sys.py
使用python
命令运行模块,接下来的其他内容是传递给程序的参数。Python将命令行参数存储在sys.argv
变量*我们使用。
请记住,运行的脚本的名称始终是sys.argv
列表中的第一个元素。所以,在这种情况下,我们将'module_using_sys.py'
as sys.argv[0]
,'we'
as sys.argv[1]
,'are'
as sys.argv[2]
和'arguments'
as sys.argv[3]
。请注意,Python从0开始计数,而不是1。
将sys.path
包含其中输入模块的目录名的列表。注意的是,在第一个字符串sys.path
是空的-这个空的字符串表示当前目录也是一部分sys.path
是相同PYTHONPATH
的环境变量。这意味着您可以直接导入位于当前目录中的模块。否则,您必须将模块放在其中一个目录中sys.path
。
请注意,当前目录是启动程序的目录。运行import os; print(os.getcwd())
以查找程序的当前目录。
字节编译的.pyc文件
导入模块是一个相对昂贵的事情,因此Python做了一些技巧,使其更快。一种方法是使用扩展创建字节编译的文件,扩展.pyc
是Python将程序转换为的中间形式(请记住Python如何工作的介绍部分?)。.pyc
当您下次从另一个程序导入模块时,此文件很有用 - 由于导入模块所需的部分处理已经完成,因此速度会快得多。此外,这些字节编译的文件与平台无关。
注意:这些.pyc
文件通常与相应的.py
文件在同一目录中创建。如果Python没有写入该目录中文件的权限,则不会创建.pyc
文件。
from..import语句
如果要将argv
变量直接导入程序(以避免sys.
每次都为其键入),则可以使用该from sys import argv
语句。
警告:通常,请避免使用该
from..import
语句,import
而是使用该语句。这是因为您的程序将避免名称冲突并且更具可读性。
例:
from math import sqrt
print("Square root of 16 is", sqrt(16))
一个模块 __name__
每个模块都有一个名称,模块中的语句可以找出其模块的名称。这对于确定模块是独立运行还是正在导入的特定目的非常方便。如前所述,当第一次导入模块时,它包含的代码将被执行。我们可以使用它来使模块以不同的方式运行,具体取决于它是单独使用还是从另一个模块导入。这可以使用__name__
模块的属性来实现。
示例(另存为module_using_name.py
):
if __name__ == '__main__':
print('This program is being run by itself')
else:
print('I am being imported from another module')
输出:
$ python module_using_name.py
This program is being run by itself
$ python
>>> import module_using_name
I am being imported from another module
>>>
这个怎么运作
每个Python模块都有自己的__name__
定义。如果是这样'__main__'
,则意味着模块由用户独立运行,我们可以采取适当的措施。
制作自己的模块
创建自己的模块很简单,你一直在做这些!这是因为每个Python程序也是一个模块。你只需要确保它有一个.py
扩展名。以下示例应该清楚说明。
示例(另存为mymodule.py
):
def say_hi():
print('Hi, this is mymodule speaking.')
__version__ = '0.1'
以上是一个示例模块。正如您所看到的,与我们通常的Python程序相比,它没有什么特别之处。接下来我们将看到如何在我们的其他Python程序中使用此模块。
请记住,模块应该放在与我们导入它的程序相同的目录中,或者放在其中一个目录中sys.path
。
另一个模块(另存为mymodule_demo.py
):
import mymodule
mymodule.say_hi()
print('Version', mymodule.__version__)
输出:
$ python mymodule_demo.py
Hi, this is mymodule speaking.
Version 0.1
这个怎么运作
请注意,我们使用相同的点分表示法来访问模块的成员。Python可以很好地重用相同的符号来赋予它独特的“Pythonic”感觉,这样我们就不必继续学习新的方法来做事。
这是一个使用from..import
语法的版本(另存为mymodule_demo2.py
):
from mymodule import say_hi, __version__
say_hi()
print('Version', __version__)
输出与输出mymodule_demo2.py
相同mymodule_demo.py
。
请注意,如果__version__
在导入mymodule的模块中已经声明了名称,则会发生冲突。这也可能是因为每个模块通常使用此名称声明其版本号。因此,总是建议您更喜欢该import
语句,即使它可能会使您的程序更长一些。
你也可以使用:
from mymodule import *
这将导入所有公共名称,例如say_hi
但不会导入,__version__
因为它以双下划线开头。
警告:请记住,您应该避免使用import-star,即
from mymodule import *
。
Python的禅宗
Python的指导原则之一是“明确比隐含更好”。
import this
在Python中运行以了解更多信息。
该dir
功能
内置dir()
函数返回对象定义的名称列表。如果对象是模块,则此列表包括在该模块内定义的函数,类和变量。
此函数可以接受参数。如果参数是模块的名称,则该函数返回该指定模块的名称列表。如果没有参数,则该函数返回当前模块的名称列表。
例:
$ python
>>> import sys
# get names of attributes in sys module
>>> dir(sys)
['__displayhook__', '__doc__',
'argv', 'builtin_module_names',
'version', 'version_info']
# only few entries shown here
# get names of attributes for current module
>>> dir()
['__builtins__', '__doc__',
'__name__', '__package__', 'sys']
# create a new variable 'a'
>>> a = 5
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'sys', 'a']
# delete/remove a name
>>> del a
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__', 'sys']
这个怎么运作
首先,我们看到dir
导入sys
模块的用法。我们可以看到它包含的巨大属性列表。
接下来,我们使用该dir
函数而不向其传递参数。默认情况下,它返回当前模块的属性列表。请注意,导入的模块列表也是此列表的一部分。
为了观察dir
实际操作,我们定义一个新变量a
并为其赋值,然后检查dir
并观察到同名列表中还有一个附加值。我们使用del
语句删除当前模块的变量/属性,并且更改将再次反映在dir
函数的输出中。
关于以下内容的注释del
:此语句用于删除变量/名称,并且在语句运行后,在这种情况下del a
,您无法再访问该变量a
- 就好像它之前从未存在过一样。
请注意,该dir()
函数适用于任何对象。例如,运行(字符串)类dir(str)
的属性str
。
还有一个vars()
函数可以为您提供属性及其值,但它不适用于所有情况。
包
到目前为止,您必须已经开始观察组织程序的层次结构。变量通常进入函数内部。函数和全局变量通常都在模块内部。如果你想组织模块怎么办?这就是包装进入图片的地方。
包只是模块的文件夹,带有一个特殊__init__.py
文件,向Python指示该文件夹是特殊的,因为它包含Python模块。
假设您想要创建一个名为'world'的包,包含'asia','africa'等子包,这些子包又包含'india','madagascar'等模块。
这是你如何构建文件夹:
- <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附带的标准库就是这样一组包和模块的一个例子。
我们已经了解了如何使用这些模块并创建自己的模块。
接下来,我们将学习一些称为数据结构的有趣概念。