Python基础教程第十章学习笔记——充电时刻

10 充电时刻

前面已经讲解了Python语言的大部分基础知识。Python的标准安装包括一组模块,称为标准库(standard library)。之前已介绍了一些模块(如math和cmath),标准库还包含其他模块。
本章将展示这些模块的工作方式,讨论如何分析他们,学习它们所提供的功能。对标准库进行概括,并着重介绍一部分有用的模块。

10.1 模块

已经学会创建和执行自己的程序(脚本)了,也学会了怎么用import从外部获取函数并为自己的程序所用:
>>> import math
>>> math.sin(0)
0.0
接下来学习一下如何编写自己的模块。

10.1.1 模块是程序

任何Python程序都可作为模块导入。
假设你写了如下程序,并将它存为hello.py文件( 名字很重要)。
#代码清单10-1 一个简单的模块
#hello.py
print "Hello, world!"
程序保存的位置也很重要,现在假设将它保存在C:\python(windows)目录中,接着可以执行下面的代码,告诉解释器在哪里寻找模块了:
>>> import sys
>>> sys.path.append('C:/python')       #告诉解释器:除了从默认的目录中寻找之外,还需要从目录c:\python中寻找模块。
现在就可以导入自己的模块了:
>>> import hello
Hello, world!
  在导入模块的时候,可能会有新文件出现——本例中是c:\python\hello,pyc。这个以.pyc为扩展名的文件是(平台无关的)经过处理(编译)的,已将转换为Python能更加有效地处理的文件。若稍后再次导入同一个模块,Python会导入.pyc文件而不是.py文件,除非.py文件已改变——这种情况下会生成新的.pyc文件。删除.pyc文件不会损害程序(只要等效的.py文件存在即可)——必要时会创建新的.pyc文件。
上边,在导入模块的时候,其中的代码就执行了。但,再次导入该模块就什么也不会发生了:
>>> import hello
>>> 
因为导入模块并不意味着在导入时执行了某些操作(如打印文本)。它们主要用于定义,比如变量、函数和类等。此外,因为只需要定义这些东西一次,导入模块多次和导入一次的效果是一样的。
这种“只导入一次”的行为在大多数情况下是一种实质性的优化,对于以下情况尤为重要:两个模块互相导入。如果每个模块都可导入数次,那就会出问题,导入再导入。。。成了无限循环。但因为第二次导入模块时什么都不会发生,所以循环会终止。
如果坚持重新导入模块,那可使用内建的reload函数,它带有一个参数(要重新加载的模块),并返回重新载入的模块——若你在程序运行的时候更改了模块并希望这些更改反映出来,那此功能比较有用。要重新载入hello模块,可:
>>> hello = reload(hello)
Hello, World!
如果已经通过实例化bar模块中的Foo类创建了一个对象x,然后重新载入bar模块,那么不管通过什么方式都无法重新创建引用bar的对象x,x仍然是旧版本Foo类的实例(源自旧版本的bar)。如果需要x基于重新载入的模块bar中的新Foo类进行创建,那就得重新创建它。

10.1.2 模块用于定义

模块在第一次导入到程序中时被执行。真正的用处在于它们(像类一样)可以保持自己的作用域——意味着定义的所有类和函数及赋值后的变量都成为了模块的特性。
1 在模块中定义函数
假设编写了一个类似代码清单10-2的模块,并将它存储为hello2.py文件。同时,假设我们将它放置到Python解释器能找到的地方——可使用前一节中的sys.path方法,也可用10.1.3节中的常规方法。
#代码清单10-2  包含函数的简单模块
#hello2.py
def hello():
    print "Hello, world!"
导入:
>>> import hello2
模块会被执行,这意味着hello函数在模块的作用域内被定义了。因此可通过以下方式来访问函数:
>>> hello2.hello()
Hello, world!
我们可通过同样的方法来使用任何在模块的全局作用域中定义的名称。
为什么这样做?为什么不直接在主程序定义好一切?主要原因是代码重用(code reuse)。如果代码放在模块中,就可在多个程序中使用这些代码了——若编写了一个非常棒的客户端数据库,并将它放到一个叫clientdb的模块中,那就可在计费的时候、发送垃圾邮件的时候以及任何需要访问客户数据的程序中使用这个模块了。所以,为了让代码可重用,请将它模块化!(也关乎抽象)
2 在模块中增加测试代码
模块用来定义函数、类和其他一些内容,但有些时候,在模块中添加一些检查模块本身是否正常工作的测试代码是很有用的。例如想确保hello函数工作正常,你可能会将hello2模块重写为新的模块——代码清单10-3中定义的hello3
#代码清单10-3 带有问题测试代码的简单模块
#hello3.py
def hello():
    print "Hello, world!"

# A test:
hello()
看起来合理——若将其作为普通程序运行,能正常工作。但作为模块导入,然后在其他程序中使用hello函数,测试代码就会被执行:
>>> import hello3
Hello, world!                    #这不是想要的
>>> hello3.hello()
Hello, world!
避免上面情况的关键在于:“告知”模块本身是作为程序运行还是导入到其他程序。为实现这一点,需使用__name__变量:
>>> __name__           #在“主程序”(包括解释器的交互式提示符在内)中,变量__name__的值时‘__main__’
'__main__'
>>> hello3.__name__      #在导入的模块中,这个值被设为模块的名字。
'hello3'
为了让模块的测试代码更加好用,可将其放置在if语句中,如代码清单10-4所示
#代码清单10-4 使用条件测试代码的模块
#hello4.py
def hello():
    print "Hello, world!"
def test():        #将测试代码放在了test函数中,也可直接放入if语句。但是这样更灵活(放入独立的test函数),即使把模块导入其他程序之后,仍可对其进行测试。
    hello()
if __name__ == '__main__': test()
如果将10-4作为程序运行,hello函数会被执行。而作为模块导入时,它的行为就会像普通模块一样:
>>> import hello4
>>> hello4.hello()
Hello, world!
仍可进行测试:
>>> hello4.test()
Hello, world!

10.1.3 让你的模块可用

前边,改变了sys.path——其中包含了(字符串组成的)一个目录列表,解释器在该列表中查找模块。
而在理想状况下,sys.path本身一开始就应该包含正确的目录(包括你的模块的目录)。有两种方法可以做到这一点:一是将模块放置在合适的位置,二是告诉解释器去哪里查找模块。
1. 将模块放置在正确的位置
只需要找出Python解释器从哪里查找模块,然后将自己的文件放置在那里就行。(如果机器上解释器由管理员安装,你没有管理员权限——可能无法将你的模块存储在Python使用的目录中,所以你需要另一个解决方案:告诉解释器去哪里查找)
那些(称为搜索路径的)目录的列表可以在sys模块中的path变量中找到:
>>> import sys, pprint
>>> pprint.pprint(sys.path)
['',
 'C:\\Users\\Administrator\\AppData\\Local\\Enthought\\Canopy\\User\\Scripts\\python27.zip',
 'C:\\Users\\Administrator\\AppData\\Local\\Enthought\\Canopy\\App\\appdata\\canopy-1.7.4.3348.win-x86_64\\DLLs',
 'C:\\Users\\Administrator\\AppData\\Local\\Enthought\\Canopy\\App\\appdata\\canopy-1.7.4.3348.win-x86_64\\lib',
 'C:\\Users\\Administrator\\AppData\\Local\\Enthought\\Canopy\\App\\appdata\\canopy-1.7.4.3348.win-x86_64\\lib\\plat-win',
 'C:\\Users\\Administrator\\AppData\\Local\\Enthought\\Canopy\\App\\appdata\\canopy-1.7.4.3348.win-x86_64\\lib\\lib-tk',
 'C:\\Users\\Administrator\\AppData\\Local\\Enthought\\Canopy\\App\\appdata\\canopy-1.7.4.3348.win-x86_64',
 'C:\\Users\\Administrator\\AppData\\Local\\Enthought\\Canopy\\User',
 'C:\\Users\\Administrator\\AppData\\Local\\Enthought\\Canopy\\User\\lib\\site-packages',
 'C:\\Users\\Administrator\\AppData\\Local\\Enthought\\Canopy\\User\\lib\\site-packages\\win32',
 'C:\\Users\\Administrator\\AppData\\Local\\Enthought\\Canopy\\User\\lib\\site-packages\\win32\\lib',
 'C:\\Users\\Administrator\\AppData\\Local\\Enthought\\Canopy\\User\\lib\\site-packages\\Pythonwin',
 'C:\\Users\\Administrator\\AppData\\Local\\Enthought\\Canopy\\App\\appdata',
 'C:\\Users\\Administrator\\AppData\\Local\\Enthought\\Canopy\\App\\appdata\\canopy-1.7.4.3348.win-x86_64\\lib\\site-packages\\win32',
 'C:\\Users\\Administrator\\AppData\\Local\\Enthought\\Canopy\\App\\appdata\\canopy-1.7.4.3348.win-x86_64\\lib\\site-packages\\win32\\lib',
 'C:\\Users\\Administrator\\AppData\\Local\\Enthought\\Canopy\\App\\appdata\\canopy-1.7.4.3348.win-x86_64\\lib\\site-packages\\Pythonwin',
 'C:\\Users\\Administrator\\AppData\\Local\\Enthought\\Canopy\\App\\appdata\\canopy-1.7.4.3348.win-x86_64\\lib\\site-packages\\IPython\\extensions',
 'C:\\Users\\Administrator\\AppData\\Local\\Enthought\\Canopy\\App\\appdata',
 'C:\\Users\\Administrator\\AppData\\Local\\Enthought\\Canopy\\App\\appdata\\canopy-1.7.4.3348.win-x86_64',
 'C:\\Users\\Administrator\\AppData\\Local\\Enthought\\Canopy\\App\\appdata\\canopy-1.7.4.3348.win-x86_64\\lib\\site-packages',
 'C:\\Users\\Administrator\\.ipython']
#如果你的数据结构过大,不能再一行打印完,可使用pprint模块中的pprint函数代替普通的print语句。pprint是个相当好的打印函数,能提供更加智能的打印输出。
上边每个字符串都提供了一个放置模块的目录,解释器可以从这些目录中找到所需的模块。这些目录都可以使用,但site_packages目录是最佳选择——它就是用来干这个的。只要将模块放入类似的site_packages这样的目录中,所有程序就都能将其导入了。
2. 告诉编译器去哪里找
“将模块放置在正确的位置”这个解决方案对以下几种情况可能不适用:
1) 不希望自己的模块填满Python解释器的目录
2) 没有在Python解释器目录中存储文件的权限
3) 想将模块放在其他地方
所以就需要告诉解释器去哪里找。之前的一种方法:编辑sys.path,但这不是通用的方法。标准的实现方法是在PYTHONPATH环境变量中包含模块所在的目录。
PYTHONPATH环境变量的内容会因为使用的操作系统不同而有所差异,但基本上,与sys.path很类似—— 一个目录列表。
#环境变量并不是Python解释器的一部分——是操作系统的一部分。基本上,它相当于Python变量,不过是在Python解释器外设置的:Windows系统,可使用控制面板编辑变量。依次点击:开始菜单-》设置-》控制面板。进入控制面板后,双击“系统”图标。在打开的对话框中选择“高级”选项卡,点击“环境变量”按钮。这时会弹出一个氛围上下两栏的对话框:其中一个是用户变量,另一个是系统变量,需修改前者。若已有PYTHONPATH项,那选中它,单击“编辑”按钮,进行编辑;若没有,单击“新建”按钮,然后使用PYTHONPATH作为“变量名”,输入文件目录作为“变量值”,多个目录以分号分隔。
3. 命名模块
包含模块代码的文件的名字要和模块名一样——再加上.py扩展名。Windows系统中,也可使用.pyw扩展名。

10.1.4 包

为了组织好模块,可将它们分组为包(package)。包基本上就是另一类模块(但是能包含其他模块)——当模块存储在文件中时(扩展名.py),包就是模块所在的目录。为了让Python将其作为包对待,它必须包含一个名为__init__py的文件(模块)。若将它作为普通模块导入的话,文件的内容就是包的内容。如:有个名为constants的包,文件constants/__init__.py包括语句PI=3.14,那可像下面一样做:
import constants
print constants
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值