title: 模块 create: 2016.12.7 modified: 2016.12.7 tags: python 标准库 sys os
6
[TOC]
Python的标准安装包括一组模块(module),称为标准库(standard library)。本章将介绍标准库中模块的功能。
In [8]:
import math
math.sin(0)
Out[8]:
怎么编写自己的模块呢?
In [1]:
#一个简单的模块
#hello.py
print "Hello, world!"
程序保存的位置很重要,假如保存在c:/python。可以执行下面的代码,告诉解释器在哪里寻找模块了(以Windows目录为例):
In [10]:
import sys
sys.path.append('c:/python')
通过上步告诉解释器:除了从默认的目录中寻找之外,还需要从目录c:/python中寻找模块。完成之后,就能导入自己的模块了:
>>> import hello
Hello, world!
如你所见,在导入模块的时候,其中的代码被执行了。不过,如果再次导入该模块,就什么都不会发生了:
>>> import hello
>>>
为什么这次没用了?因为导入模块并不意味着在导入时执行某些操作(比如打印文本)。它们主要用于定义,比如变量、函数和类等。此外,因为只需要定义这些东西一次,导入模块多次和导入一次的效果是一样的。
In [1]:
#包含函数的简单模块
#hello2.py
def hello():
print "Hello, world!"
可以像下面这样导入:
>>>import hello2
模块会被执行,这意味着hello函数在模块的作用域内被定义了。因此可以通过以下方式来访问函数:
>>>hello2.hello()
Hello, world!
为什么要这样做呢?为什么不在主程序中定义好一切呢?主要原因是代码重用(code reuse)。如果把代码放在模块中,就可以在多个程序中使用这些代码了。因此请记住:为了让代码可重用,请将它模块化!
1.2.2 在模块中添加测试代码
模块用来定义函数、类和其他一些内容,但是有些时候,在模块中添加一些检查模块本身是否正常工作的测试代码是很有用的。如下:
In [ ]:
#带有问题测试代码的简单模块
#hello3.py
def hello():
print "Hello, world!"
#A test:
hello()
>>>import hello3
Hello, world!
>>>hello3.hello()
Hello, world!
如果将hello3作为模块导入,测试代码就会被执行。为了避免这种情况关键在于:“告知”模块本身是作为程序运行还是导入到其他程序。为了实现这一点,需要使用__name__变量:
In [4]:
__name__
Out[4]:
hello3.__name__
'hello3'
如上,在“主程序”中,变量__name__的值是‘__main__’。而在导入的模块中,这个值就被设定为模块的名字。因此,为了让模块的测试代码更加好用,可以将其放置在if语句中:
In [ ]:
#使用条件测试代码的模块
#hello4.py
def hello():
print "Hello, world!"
def test():
hello()
if __name__=='__main__':
test()
In [ ]:
import constants
print constants.PI
In [5]:
import copy
没有引发异常—所以它是存在的。但是它能做什么?又有什么?
In [13]:
[n for n in dir(copy) if not n.startswith('_')]
Out[13]:
In [7]:
copy.__name__
Out[7]:
In [9]:
copy.__all__
Out[9]:
__all__是在copy模块内部被设置的,如下:
__all__=['Error', 'copy', 'deepcopy']
那么它为什么在那呢?它定义了模块的公有接口(public interface)。更准确地说,它告诉解释器:从模块导入所有名字代表什么含义。如果你使用如下代码:
from copy import *
那么,你只能使用__all__变量中的3个函数。要导入PyStringMap函数的话,你就得显式地实现,比如from copy import PyStringMap。
在编写模块的时候,像设置__all__这样的技术是相对有用的。因为模块中可能会有一大堆其他程序不需要或不想要的变量、函数和类,__all__会“客气地”将它们过滤掉。如果没有设定__all__,用import *语句默认将会输出模块中所有不以下划线开头的全局名称。
In [14]:
help(copy.copy)
In [15]:
copy.copy.__doc__
Out[15]:
文档字符串是写在函数开头并且简述函数功能的字符串。这个字符串可以通过函数的__doc__属性引用。模块和类都有文档字符串(写在开头)。
使用help与直接检查文档字符串相比,它的好处在于会获得更多信息,比如函数签名(也就是所带的参数)。
In [17]:
copy.__file__
Out[17]:
注意,一些模块并不包含任何可以阅读的Python源代码。它们可能已经融入到解释器内了(比如sys模块),或者可能是使用C语言写成的。
In [ ]: