python基础教程_学习笔记12:充电时刻——模块

充电时刻——模块

python的标准安装包括一组模块,称为标准库。

模块

>>> import math

>>> math.sin(0)

0.0

模块是程序

任何python程序都可以作为模块导入。

$ cat hello.py

#!/usr/bin/python

print "Hello,signjing!"

$ ./hello.py

Hello,signjing!

假设将python程序保存在/home/ggz2/magiccube/mysh/pys目录中,执行下面的代码:

>>> import sys

>>> sys.path.append(‘/home/ggz2/magiccube/mysh/pys‘)

这里所做的只是告诉解释器:除了从默认的目录中寻找之外,还需要从目录/home/ggz2/magiccube/mysh/pys中寻找模块。完成这个步骤后,就能导入自己的模块了:

>>> import hello

Hello,signjing!

注意:在导入模块的时候,可能会看到有新文件出现,本例中是/home/ggz2/magiccube/mysh/pys/hello.pyc。这个以.pyc为扩展名的文件是(平台无关的)经过处理(编译)的,已经转换成python能够更加有效地处理的文件。如果稍后导入同一个模块,python会导入.pyc文件而不是.py文件,除非.py文件已经改变——在这种情况下,会生成新的.pyc文件。删除.pyc文件不会损害程序(只要等效的.py文件存在即可)——必要的时候会创建新的.pyc文件。

如你所见,在导入模块的时候,其中的代码就被执行了。不过再次导入该模块,就不会发生什么了。

>>> import hello

>>>

因为导入模块并不意味着在导入时执行某些操作。它们主要用于定义。此外,因为只需要定义这些东西一次,导入模块多次和导入一次的效果是一样的。

模块用于定义

模块在第一次导入程序中时被执行。这看起来有点用——但并不算很有用。真正的用处在于它们(像类一样)可以保持自己的作用域。这就意味着定义的所有类和函数以及赋值后的变量都成为了模块的特性。

在模块中定义函数

$ cat hello2.py

#!/usr/bin/python

def hello():

print "morning,signjing"

>>> import hello2

>>> hello2.hello()

morning,signjing

可以通过同样的方法来使用任何在模块的全局作用域中定义的名称。

为了让代码可重用,请将它模块化!

在模块中增加测试代码

模块用来定义函数、类和其他一些内容,但有些时候(事实上是经常),在模块中添加一些检查模块本身是否正常工作的测试代码是很有用的。

$ cat  hello3.py

#!/usr/bin/python

def hello():

print "Hello!"

# a test

hello()

>>> import hello3

Hello!

>>> hello3.hello()

Hello!

避免这种情况的关键在于:“告知”模块本身是作为程序运行还是导入到其他程序。为了实现这一点,需要使用__name__(双下划线)变量:

>>> __name__

‘__main__‘

>>> hello3.__name__

‘hello3‘

可见,在主程序(包括解释器的交互式提示符在内)中,变量__name__的值是’__main__’。而在导入的模块中,这个值被设定为模块的名字。因此,为了让模块的测试代码更加好用,可以将其放置在if语句中:

$ cat hello4.py

#!/usr/bin/python

def hello():

print "hello"

def test():

hello()

if __name__==‘__main__‘:test()

>>> import hello4

>>>

>>> hello4.hello()

hello

让你的模块可用

将模块放置在正确位置

将你的模块放置在正确位置(或者某个正确位置)是很容易的。只需要找出python解释器从哪里查找模块,然后将自己的文件放置在那里即可。

linux系统:

>>> import sys,pprint

>>> pprint.pprint(sys.path)

[‘‘,

‘/usr/lib64/python26.zip‘,

‘/usr/lib64/python2.6‘,

‘/usr/lib64/python2.6/plat-linux2‘,

‘/usr/lib64/python2.6/lib-tk‘,

‘/usr/lib64/python2.6/lib-old‘,

‘/usr/lib64/python2.6/lib-dynload‘,

‘/usr/lib64/python2.6/site-packages‘,

‘/usr/lib64/python2.6/site-packages/gtk-2.0‘,

‘/usr/lib/python2.6/site-packages‘]

windows系统:

>>> import sys,pprint

>>> pprint.pprint(sys.path)

[‘‘,

‘D:\\software(x86)\\Python27\\Lib\\idlelib‘,

‘C:\\Windows\\system32\\python27.zip‘,

‘D:\\software(x86)\\Python27\\DLLs‘,

‘D:\\software(x86)\\Python27\\lib‘,

‘D:\\software(x86)\\Python27\\lib\\plat-win‘,

‘D:\\software(x86)\\Python27\\lib\\lib-tk‘,

‘D:\\software(x86)\\Python27‘,

‘D:\\software(x86)\\Python27\\lib\\site-packages‘]

每个字符串都提供了一个放置模块的目录,解释器可以从这些目录中找到所需的模块。尽管这些目录都可以使用,但site-packages目录是最佳选择,因为它就是用来做这些事情的。

在windows操作系统中的D:\\software(x86)\\Python27\\lib\\site-packages下创建文件another_hello.py:

def hello():

print "hello,Win7"

>>> import another_hello

>>> another_hello.hello()

hello,Win7

可见,只要将模块放入类似site-packages这样的目录中,所有程序就都能将其导入了。

告诉编译器去哪里找

“将模块放置在正确的位置”这个解决方案在以下几种情况下可能并不适用:

1)不希望将自己的模块填满python解释器的目录;

2)没有python解释器目录中存储文件的权限;

3)想将模块放在其他地方

既然如此,那就告诉解释器去哪里找。之前提到了sys.path,但这不是通用的方法。标准的实现方法是在PYTHONPATH环境变量中包含模块所在的目录。

PYTHONPATH环境变量的内容会因为使用的操作系统不同而有所差异,但从基本上来说,它与sys.path很类似——一个目录列表。

环境变量并不是python解释器的一部分,它们是操作系统的一部分。

提示:不需要使用PYTHONPATH来更改sys.path。路径配置文件提供了一个有用的捷径,可以让python替你完成这些工作。路径配置文件是以.pth为扩展名的文件,包括应该添加到sys.path中的目录信息。空行和以#开头的行都会被忽略。以import开头的文件会被执行。对于Windows来说,使用sys.prefix定义的目录名;在unix和mac OSX中则使用site-packages目录。

命名模块

包含模块代码的文件要和模块名一样——再加上.py扩展名。在windows系统中,也可以使用.pyw扩展名。

为了组织好模块,可以将它们分组为包。包基本上就是另外一类模块。有趣的地方就是它们都能包含其他模块。当模块存储在文件中时(扩展名为.py),包就是模块所在的目录。为了让python将其作为包对待,它必须包含一个命名为__init__py的文件(模块)。如果将它作为普通模块导入的话,文件的内容就是包的内容。比如有个名为constants的包,文件constants/__init__.py包括语句PI=3.14,那么可以这么做:

import constants

print constants.PI

为了将模块放置在包内,直接把模块放在包目录内即可。

探究模块

如何独立地探究模块,是极有价值的技能。因为职业生涯中可能会遇到很多有用的模块。

模块中有什么

探究模块最直接的方式就是在python解释器中研究它们。第一件事就是导入它。

假设有个叫做copy的标准模块:

>>> import copy

使用dir

查看模块中包含的内容可以使用dir函数,会将对象(以及模块的所有函数、类、变量等)的所有特性列出。

>>> dir(copy)

[‘Error‘, ‘PyStringMap‘, ‘_EmptyClass‘, ‘__all__‘, ‘__builtins__‘, ‘__doc__‘, ‘__file__‘, ‘__name__‘, ‘__package__‘, ‘_copy_dispatch‘, ‘_copy_immutable‘, ‘_copy_inst‘, ‘_copy_with_constructor‘, ‘_copy_with_copy_method‘, ‘_deepcopy_atomic‘, ‘_deepcopy_dict‘, ‘_deepcopy_dispatch‘, ‘_deepcopy_inst‘, ‘_deepcopy_list‘, ‘_deepcopy_method‘, ‘_deepcopy_tuple‘, ‘_keep_alive‘, ‘_reconstruct‘, ‘_test‘, ‘copy‘, ‘deepcopy‘, ‘dispatch_table‘, ‘error‘, ‘name‘, ‘t‘, ‘weakref‘]

一些名字以下划线开始——暗示(约定俗成)它们并不是为在模块外部使用而准备的。过滤到它们:

>>> [n for n in dir(copy) if not n.startswith(‘_‘)]

[‘Error‘, ‘PyStringMap‘, ‘copy‘, ‘deepcopy‘, ‘dispatch_table‘, ‘error‘, ‘name‘, ‘t‘, ‘weakref‘]

all变量

__all__这个名字包含一个列表,在copy模块内部被设置。

>>> copy.__all__

[‘Error‘, ‘copy‘, ‘deepcopy‘]

它定义了模块的公共接口。更准确地说,它告诉解释器:从模块导入所有名字代表什么含义。

使用如下代码from copy import *,则只能使用__all__变量中的函数。要导入PyStringMap的话,就得显式地实现,或者导入copy然后使用copy.PyStringMap,或者使用from copy import PyStringMap。

在编写模块的时候,像设置__all__这样的技术还是相当有用的。因为模块中可能会有一大堆其他程序不需要或不想要的变量、函数和类,__all__会“客气地”将它们过滤了出去。如果没有设定__all__,用import *语句默认将会输出模块中所有不以下划线开头的全局名称。

用help获取帮助

对于探究工作,交互式解释器是个非常强大的工具,而对该语言的精通程度决定了对模块探究的程度。不过还有个标准函数能够为你提供日常所需的信息,这个函数叫做help。

>>> help(copy.copy)

Help on function copy in module copy:

copy(x)

Shallow copy operation on arbitrary Python objects.

See the module‘s __doc__ string for more info.

>>>

事实上,上面的帮助文档是从copy函数的文档字符串中提取出的:

>>> print copy.copy.__doc__

Shallow copy operation on arbitrary Python objects.

See the module‘s __doc__ string for more info.

>>>

使用help与直接检查文档字符串相比,好处在于获得更多信息。

help(copy)会打印出更多信息,此处略;

文档

并非每个模块或函数都有不错的文档字符串(尽管都应该有),有些时候可能需要十分透彻地描述这些模块和函数是如何工作的。

学习python编程最有用的文档莫过于python库参考,它对所有标准库中的模块都有描述。

使用源代码

对于希望真正理解python语言的人来说,要了解模块,是不能脱离源代码的。

阅读源代码事实上是学习python最好的方式——除了自己编写代码外。

真正的阅读不是问题,但是问题在于源代码那里。如果希望阅读标准模块copy的源代码,一种方案是检查sys.path,然后自己找;另一种是检查模块的__file__属性:

>>> copy.__file__

‘D:\\software(x86)\\Python27\\lib\\copy.pyc‘

注意:一些模块并不包含任何可以阅读的python源代码。它们可能已经融入到解释器内了(比如sys模块),或者可能是使用c语言写成的。

python基础教程_学习笔记12:充电时刻——模块

时间: 2024-10-05 21:05:57

python基础教程_学习笔记12:充电时刻——模块的相关文章

python基础教程_学习笔记5:字符串

字符串 基本字符串操作 字符串也是序列,因此序列的基本操作(索引.分片.连接.乘法.长度.求最大值和最小值.成员资格)对字符串同样适用: 索引 >>> 'a_string'[0] 'a' 长度 >>> len('a_string') 8 求最大值 >>> max('a_string') 't' 求最小值 >>> min('a_string') '_' 乘法 >>> 'a_string'*2 'a_stringa_st

python基础教程_学习笔记15:标准库:一些最爱——fileinput

标准库:一些最爱 fileinput 重要的函数 函数 描述 input([files[,inplace[,backup]]) 便于遍历多个输入流中的行 filename() 返回当前文件的名称 lineno() 返回当前(累计)的名称 filelineno() 返回当前文件的行数 isfirstline() 检查当前行是否是文件的第一行 isstdin() 检查最后一行是否来自sys.stdin nextfile() 关闭当前文件,移动到下一个文件 close() 关闭序列 fileinput

python基础教程_学习笔记16:标准库:一些最爱——random

标准库:一些最爱 random random模块包括返回随机数的函数,可以用于模拟或者用于任何产生随机输出的程序. 事实上,所产生的数字都是伪随机数,它们以一个可预测的系统作为基础,除非是为了强加密的目标,否则这些随机数还是足够随机的.如果真的需要随机性,可以使用os模块的urandom函数. 重要函数 函数 描述 random() 返回0<=n<1之间的随机实数n,其中0<n<=1 getrandbits(n) 以长整型形式返回n个随机位(二进制数) uniform(a,b) 返

python基础教程_学习笔记17:标准库:一些最爱——time

标准库:一些最爱 time time模块所包含的函数能够实现以下功能: 获取当前时间.操作系统时间和日期.从字符串读取时间以及格式化时间为字符串. 日期可以用实数(从"新纪元"的1月1日0点开始计算到现在的秒数,新纪元是一个与平台相关的年份,对unix来说是1970年),或者是包含有9个整数的元组. 日期元组的字段含义 如元组: (2008,1,21,12,2,56,0,21,0) 表示2008年1月21日12时2分56秒,星期一,且是当年的第21天(无夏令时). 索引 字段 值 0

python基础教程_学习笔记14:标准库:一些最爱——re

标准库:一些最爱 re re模块包含对正则表达式的支持,因为曾经系统学习过正则表达式,所以基础内容略过,直接看python对于正则表达式的支持. 正则表达式的学习,见<Mastering Regular Expressions>(精通正则表达式) re模块的内容 最重要的一些函数 函数 描述 compile(pattern[,flags]) 根据包含正则表达式的字符串创建模式对象 search(pattern,string[,flags]) 在字符串中寻找模式 match(pattern,st

python基础教程_学习笔记2:序列-2

序列-2 通用序列操作 序列相加 通过加号对列表进行连接操作: 列表 >>> [1,3,4]+[2,5,8] [1, 3, 4, 2, 5, 8] 字符串 >>> '134'+'258' '134258' 元组 >>> (1,2,3)+(2,5,8) (1, 2, 3, 2, 5, 8) 元素数据类型不同的列表 >>> [[1,3],[3,9]]+[[2,2],'abc'] [[1, 3], [3, 9], [2, 2], 'abc'

python基础教程_学习笔记20:标准库:一些最爱——os

标准库:一些最爱 os os模块为你提供了访问多个操作系统服务的功能. os和它的子模块os.path还包括一些用于检查.构造.删除目录和文件的函数,以及一些处理路径的函数. os模块中一些重要函数和变量 函数/变量 描述 environ 对环境变量进行映射 system(command) 在子shell中执行操作系统命令 sep 路径中的分隔符 pathsep 分隔路径的分隔符 linesep 行分隔符('\n','\r','\r\n') urandom(n) 返回n字节的加密强随机数据 os

python基础教程_学习笔记13:标准库:一些最爱——sys

标准库:一些最爱 sys sys这个模块让你能够访问与python解释器联系紧密的变量和函数. sys模块中一些重要的函数和变量 函数/变量 描述 argv 命令行参数,包括脚本名称 exit([arg]) 退出当前程序,可选参数为给定的返回值或者错误信息 modules 映射模块名字到载入模块的字典 path 查找模块所在目录的目录名列表 platform 类似sunos5或者win32的平台标识符 stdin 标准输入流--一个类文件对象 stdout 标准输出流--一个类文件对象 stde

python基础教程_学习笔记7:条件、循环、其它语句

条件.循环.其它语句 print和import 随着更加深入地学习python,可能会出现这种感觉:有些自以为已经掌握的知识点,还隐藏着一些让人惊讶的特性. 使用逗号输出 打印多个表达式,只要将这些表达式用逗号隔开即可: >>> print "age:",28 age: 28 参数之间都插入了一个空格符. 如果在结尾加上逗号,那么接下来的语句会与前一条语句在同一行打印: print "Hello,", print "World!"