模块:在Python中,一个.py文件就称之为一个模块(Module)
包:为了避免模块名冲突,Python又引入了按目录来组织模块的方法,称为包(Package)
一个
abc.py
的文件就是一个名字叫abc
的模块,一个xyz.py
的文件就是一个名字叫xyz
的模块。
abc.py
模块的名字就变成了mycompany.abc
,类似的,xyz.py
的模块名变成了mycompany.xyz
。
请注意,每一个包目录下面都会有一个__init__.py
的文件,这个文件是必须存在的,否则,Python就把这个目录当成普通目录,而不是一个包。__init__.py
可以是空文件,也可以有Python代码,因为__init__.py
本身就是一个模块,而它的模块名就是mycompany
类似的,可以有多级目录,组成多级层次的包结构。比如如下的目录结构:
www.py
的模块名就是
mycompany.web.www
,两个文件
utils.py
的模块名分别是
mycompany.utils
和
.web.util
#!/usr/bin/env python
# -*- coding: utf-8 -*-
' a test module '
__author__ = 'Michael Liao'
import sys
def test():
args = sys.argv
if len(args)==1:
print 'Hello, world!'
elif len(args)==2:
print 'Hello, %s!' % args[1]
else:
print 'Too many arguments!'
if __name__=='__main__':
test()
第1行和第2行是标准注释,第1行注释可以让这个hello.py
文件直接在Unix/Linux/Mac上运行,第2行注释表示.py文件本身使用标准UTF-8编码;
第4行是一个字符串,表示模块的文档注释,任何模块代码的第一个字符串都被视为模块的文档注释;
第6行使用__author__
变量把作者写进去,这样当你公开源代码后别人就可以瞻仰你的大名
导入sys
模块后,我们就有了变量sys
指向该模块,利用sys
这个变量,就可以访问sys
模块的所有功能。
sys
模块有一个argv
变量,用list存储了命令行的所有参数。argv
至少有一个元素,因为第一个参数永远是该.py文件的名称
if __name__=='__main__':
test()
当我们在命令行运行hello
模块文件时,Python解释器把一个特殊变量__name__
置为__main__
,而如果在其他地方导入该hello
模块时,if
判断将失败,因此,这种if
测试可以让一个模块通过命令行运行时执行一些额外的代码,最常见的就是运行测试
理解:别的地方导入改模块时,_name_不是_main_,不执行test()函数,需要调用。
别名
导入模块时,还可以使用别名,这样,可以在运行时根据当前环境选择最合适的模块。比如Python标准库一般会提供StringIO
和cStringIO
两个库,这两个库的接口和功能是一样的,但是cStringIO
是C写的,速度更快,所以,你会经常看到这样的写法:
try:
import cStringIO as StringIO
except ImportError: # 导入失败会捕获到ImportError
import StringIO
这样就可以优先导入cStringIO
。如果有些平台不提供cStringIO
,还可以降级使用StringIO
。导入cStringIO
时,用import ... as ...
指定了别名StringIO
,因此,后续代码引用StringIO
即可正常工作。
作用域
正常的函数和变量名是公开的(public),可以被直接引用,比如:abc
,
x123
,
PI
等,有的函数和变量我们希望仅仅在模块内部使用。在Python中,是通过_
前缀来实现的
类似
__xxx__
这样的变量是特殊变量,可以被直接引用,但是有特殊用途,比如上面的
__author__
,
__name__
就是特殊变量,
hello
模块定义的文档注释也可以用特殊变量
__doc__
访问,我们自己的变量一般不要用这种变量名
private函数或变量不应该被别人引用,那它们有什么用呢?请看例子:
def _private_1(name):
return 'Hello, %s' % name
def _private_2(name):
return 'Hi, %s' % name
def greeting(name):
if len(name) > 3:
return _private_1(name)
else:
return _private_2(name)
我们在模块里公开greeting()
函数,而把内部逻辑用private函数隐藏起来了,这样,调用greeting()
函数不用关心内部的private函数细节,这也是一种非常有用的代码封装和抽象的方法
安装第三方模块
在Python中,安装第三方模块,是通过setuptools这个工具完成的。Python有两个封装了setuptools的包管理工具:easy_install
和pip
。目前官方推荐使用pip
。mac默认安装。
pip install PIL
import Image
>>> im = Image.open('test.png')
>>> print im.format, im.size, im.mode
其他常用的第三方库还有MySQL的驱动:MySQL-python
,用于科学计算的NumPy库:numpy
,用于生成文本的模板工具Jinja2
,等等。
默认情况下,Python解释器会搜索当前目录、所有已安装的内置模块和第三方模块,搜索路径存放在sys
模块的path
变量中:
>>> import sys
>>> sys.path
['', '/Library/Python/2.7/site-packages/pycrypto-2.6.1-py2.7-macosx-10.9-intel.egg', '/Library/Python/2.7/site-packages/PIL-1.1.7-py2.7-macosx-10.9-intel.egg', ...]
使用__future__
导入高版本的模块,在低版本中体验高版本的特性,兼容高版本!'xxx'
表示str,Unicode字符串用
u'xxx'
表示unicode,而在3.x中,所有字符串都被视为unicode,因此,写
u'xxx'
和
'xxx'
是完全一致的,而在2.x中以
'xxx'
表示的str就必须写成
b'xxx'
,以此表示“二进制字符串”。
在Python 2.x中,对于除法有两种情况,如果是整数相除,结果仍是整数,余数会被扔掉,这种除法叫“地板除”:
>>> 10 / 3
3
而在Python 3.x中,所有的除法都是精确除法,
10 / 3
3.3333333333333335
如果你想在Python 2.7的代码中直接使用Python 3.x的除法,可以通过__future__
模块的division
实现:
from __future__ import division
print '10 / 3 =', 10 / 3
print '10.0 / 3 =', 10.0 / 3
print '10 // 3 =', 10 // 3
结果如下:
10 / 3 = 3.33333333333
10.0 / 3 = 3.33333333333
10 // 3 = 3