简介

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

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

有各种编写模块的方式,但最简单的方式是创建一个以.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自带的标准库正是一组包和模块的范例。

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

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

简明Python3教程 10.模块的更多相关文章

  1. 简明Python3教程(A Byte of Python 3)

    关键字:[A Byte of Python v1.92(for Python 3.0)] [A Byte of Python3] 简明Python教程 Python教程 简明Python3教程  简明 ...

  2. 简明Python3教程 9.函数

    简介 函数是程序的可复用片段,允许你为语句块赋予名字之后在程序的任何地方运行它们任意次,这称做函数调用. 我们已经使用过一些内建函数,例如len和range等. 函数也许是任何有意义的软件中最重要的构 ...

  3. 简明Python3教程 18.下一步是什么

    如果你有认真通读本书之前的内容并且实践其中包含的大量例程,那么你现在一定可以熟练使用python了. 同时你可能也编写了一些程序用于验证python特性并提高你的python技能.如果还没有这样做的话 ...

  4. 简明Python3教程 16.标准库

    简介 python标准库作为python标准安装的一部分,其自身包含数量庞大的实用模块, 因此熟悉python标准库非常重要,因为很多问题都能利用python标准库快速解决. 下面我们将研究标准库中的 ...

  5. 简明Python3教程 12.问题解决

    我们已经探究了python语言的方方面面,现在我们将通过设计编写一个有用的程序将这些内容有机的结合起来. 主要目标是让大家有能力独自编写程序. 问题 我们要解决的问题是”希望编写一个程序,用于创建所有 ...

  6. 简明Python3教程 6.基础

    你肯定不满足于只打印"Hello World"吧? 你想要的更多 - 你希望得到一些输入,操纵它后再从中得到某些东西.我们可以使用python中的常量和变量实现这些功能. 字面常量 ...

  7. 简明Python3教程 5.第一步

    介绍 我们现在来看看如何在Python中运行传统的”Hello world”程序.这会教你如何写.保存以及运行Python程序. 有两种办法来运行您的Python程序——使用交互式的解释器提示符或者源 ...

  8. 简明python教程四-----模块

    模块基本是一个包含了所有你定义的函数和变量的文件.为了在其他程序中重用模块,模块的文件名必须以.py为扩展名. #!/usr/bin/python #Filename:using_sys.py imp ...

  9. 简明Python3教程 1.介绍

    Python是少有的几种既强大又简单的编程语言.你将惊喜地发现通过使用Python即可轻松专注于解决问题而非和你所用的语言格式与结构. 下面是Python的官方介绍: Python is an eas ...

随机推荐

  1. Activex调试以及m_hWnd为空 解决办法

    1. 点击[开始]->[运行] 命令:regedit.2. 定位到HKEY_LOCALMACHINE -> SOFTWARE -> Microsoft -> Internet ...

  2. js进阶 12-4 jquery键盘事件如何使用

    js进阶 12-4 jquery键盘事件如何使用 一.总结 一句话总结:键盘和鼠标都是外设输入设备,所以函数很像,所以使用就像鼠标事件click一样 1.jquery键盘事件有哪三个? 1(up和do ...

  3. 简单的Java多线程的使用

    前几天做一个功能.就是在前台更改信息后会自己主动发邮件给其它的人,相关信息已更改,刚開始是直接在更改信息代码后面增加发送邮件的代码,但发现这样会使界面特别慢,而慢的主要原因是因为发送邮件有时会耗时非常 ...

  4. 用Apache Ivy实现项目里的依赖管理 分类: C_OHTERS 2014-07-06 18:11 564人阅读 评论(0) 收藏

    Apache Ivy是一个管理项目依赖的工具. 它与Maven  Apache Maven 构建管理和项目管理工具已经吸引了 Java 开发人员的注意.Maven 引入了 JAR 文件公共存储库的概念 ...

  5. JAVA 中无锁的线程安全整数 AtomicInteger介绍和使用

    Java 中无锁的线程安全整数 AtomicInteger,一个提供原子操作的Integer的类.在Java语言中,++i和i++操作并不是线程安全的,在使用的时候, 不可避免的会用到synchron ...

  6. [内核编程] 4.5 HOOK分发函数

    4.5 HOOK分发函数 本节开始深入的探讨键盘的过滤与反过滤.有趣的是,无论是过滤还是反过 滤,其原理都是进行过滤.取胜的关键在于:谁将第一个得到信息. 黑客可能会通过修改一个已经存在的驱动对象(比 ...

  7. CentOS下安装和配置MySQL-JDK-Tomcat-Nginx(个人官网环境搭建手册)

    今天,重新弄我的个人云主机的环境,准备运营自己用Java写的个人官网等网站. 服务器环境:阿里云CentOS 6.4位 包括以下脚本在内的绝大部分命令和脚本,都是我亲自执行过,靠谱的. 完整的&quo ...

  8. 《高性能MySQL》--复制笔记

    复制解决的问题 1,数据分布 MySQL复制通常不会对带宽造成很大的压力,但在5.1版本引入的基于行的复制会比传统的基于语句的复制模式的带宽压力更大.你可以随意地停止或开始复制,并在不同的地理位置来分 ...

  9. android生成分享长图而且加入全图水印

    尊重他人的劳动成果.转载请标明出处:http://blog.csdn.net/gengqiquan/article/details/65938021. 本文出自:[gengqiquan的博客] 领导近 ...

  10. [React] Render Basic SVG Components in React

    React loves svg just as much as it loves html. In this lesson we cover how simple it is to make SVG ...