本书是超过3,000个新闻组讨论的精华部分,当然也有很多的新脚本,为了涵盖标准库的每个角落.
我尽力使得每个脚本都易于理解,易于重用代码.我有意缩短注释的长度,如果你想更深入地了解背景,那么你可以参阅每个Python发布中的参考手册.本书的重要之处在于范例代码.
为什么没有Tkinter
产品细节
本书使用DocBookSGML编写,我使用了一系列的工具,包括SecretLabs'PythonWorks,ExcosoftDocumentor,JamesClark'sJadeDSSSLprocessor,NormWalsh'sDocBookstylesheets,当然,还有一些Python脚本.
感谢帮忙校对的人们:TimPeters,GuidovanRossum,DavidAscher,MarkLutz,和RaelDornfest,以及PythonWare成员:MatthewEllis,HkanKarlsson,和RuneUhlin.
本书使用以下习惯用法:
斜体
等宽字体e.g.Python
等宽粗体
除非提到,所有例子都可以在Python1.5.2和Python2.0下运行.能不能在Python2.4/2.5下执行.....看参与翻译各位的了.
大多例子的文件名都包含它所使用的模块名称,后边是"-example-"以及一个唯一的"序号".注意有些例子并不是按顺序出现的,这是为了匹配本书的较早版本-(theeff-botguideto)TheStandardPythonLibrary.
本章描述了一些基本的标准库模块.任何大型Python程序都有可能直接或间接地使用到这类模块的大部分.
下面的这两个模块比其他模块加在一起还要重要:定义内建函数(例如len,int,range...)的__builtin__模块,以及定义所有内建异常的exceptions模块.
Python在启动时导入这两个模块,使任何程序都能够使用它们.
标准库里有许多用于支持内建类型操作的库.string模块实现了常用的字符串处理.math模块提供了数学计算操作和常量(pi,e都属于这类常量),cmath模块为复数提供了和math一样的功能.
re模块为Python提供了正则表达式支持.正则表达式是用于匹配字符串或特定子字符串的有特定语法的字符串模式.
这个模块包含Python中使用的内建函数.一般不用手动导入这个模块;Python会帮你做好一切.
Python允许你实时地创建函数参数列表.只要把所有的参数放入一个元组中,然后通过内建的apply函数调用函数.如Example1-1.
File:builtin-apply-example-1.pydeffunction(a,b):printa,bapply(function,("whither","canada"))apply(function,(1,2+3))whithercanada15要想把关键字参数传递给一个函数,你可以将一个字典作为apply函数的第3个参数,参考Example1-2.
File:builtin-apply-example-2.pydeffunction(a,b):printa,bapply(function,("crunchy","frog"))apply(function,("crunchy",),{"b":"frog"})apply(function,(),{"a":"crunchy","b":"frog"})crunchyfrogcrunchyfrogcrunchyfrogapply函数的一个常见用法是把构造函数参数从子类传递到基类,尤其是构造函数需要接受很多参数的时候.如Example1-3所示.
File:builtin-apply-example-3.pyclassRectangle:def__init__(self,color="white",width=10,height=10):print"createa",color,self,"sized",width,"x",heightclassRoundedRectangle(Rectangle):def__init__(self,**kw):apply(Rectangle.__init__,(self,),kw)rect=Rectangle(color="green",height=100,width=100)rect=RoundedRectangle(color="blue",height=20)createagreen
下面两个语句是等价的:
result=function(*args,**kwargs)result=apply(function,args,kwargs)1.2.2.加载和重载模块如果你写过较庞大的Python程序,那么你就应该知道import语句是用来导入外部模块的(当然也可以使用from-import版本).不过你可能不知道import其实是靠调用内建函数__import__来工作的.
通过这个戏法你可以动态地调用函数.当你只知道模块名称(字符串)的时候,这将很方便.Example1-4展示了这种用法,动态地导入所有以"-plugin"结尾的模块.
File:builtin-import-example-1.pyimportglob,osmodules=[]formodule_fileinglob.glob("*-plugin.py"):try:module_name,ext=os.path.splitext(os.path.basename(module_file))module=__import__(module_name)modules.append(module)exceptImportError:pass#ignorebrokenmodules#sayhellotoallmodulesformoduleinmodules:module.hello()example-pluginsayshello注意这个plug-in模块文件名中有个"-"(hyphens).这意味着你不能使用普通的import命令,因为Python的辨识符不允许有"-".
Example1-5展示了Example1-4中使用的plug-in.
File:example-plugin.pydefhello():print"example-pluginsayshello"Example1-6展示了如何根据给定模块名和函数名获得想要的函数对象.
File:builtin-import-example-2.pydefgetfunctionbyname(module_name,function_name):module=__import__(module_name)returngetattr(module,function_name)printrepr(getfunctionbyname("dumbdbm","open"))
File:builtin-import-example-3.pyclassLazyImport:def__init__(self,module_name):self.module_name=module_nameself.module=Nonedef__getattr__(self,name):ifself.moduleisNone:self.module=__import__(self.module_name)returngetattr(self.module,name)string=LazyImport("string")printstring.lowercaseabcdefghijklmnopqrstuvwxyzPython也提供了重新加载已加载模块的基本支持.[Example1-8#eg-1-8会加载3次hello.py文件.
File:builtin-reload-example-1.pyimporthelloreload(hello)reload(hello)helloagain,andwelcometotheshowhelloagain,andwelcometotheshowhelloagain,andwelcometotheshowreload直接接受模块作为参数.
[!Feather注:^原句无法理解,稍后讨论.]注意,当你重加载模块时,它会被重新编译,新的模块会代替模块字典里的老模块.但是,已经用原模块里的类建立的实例仍然使用的是老模块(不会被更新).
同样地,使用from-import直接创建的到模块内容的引用也是不会被更新的.
dir返回由给定模块,类,实例,或其他类型的所有成员组成的列表.这可能在交互式Python解释器下很有用,也可以用在其他地方.Example1-9展示了dir函数的用法.
File:builtin-dir-example-1.pydefdump(value):printvalue,"=>",dir(value)importsysdump(0)dump(1.0)dump(0.0j)#complexnumberdump([])#listdump({})#dictionarydump("string")dump(len)#functiondump(sys)#module0=>[]1.0=>[]0j=>['conjugate','imag','real'][]=>['append','count','extend','index','insert','pop','remove','reverse','sort']{}=>['clear','copy','get','has_key','items','keys','update','values']string=>[]
File:builtin-dir-example-2.pyclassA:defa(self):passdefb(self):passclassB(A):defc(self):passdefd(self):passdefgetmembers(klass,members=None):#getalistofallclassmembers,orderedbyclassifmembersisNone:members=[]forkinklass.__bases__:getmembers(k,members)formindir(klass):ifmnotinmembers:members.append(m)returnmembersprintgetmembers(A)printgetmembers(B)printgetmembers(IOError)['__doc__','__module__','a','b']['__doc__','__module__','a','b','c','d']['__doc__','__getitem__','__init__','__module__','__str__']getmembers函数返回了一个有序列表.成员在列表中名称出现的越早,它所处的类层次就越高.如果无所谓顺序的话,你可以使用字典代替列表.
[!Feather注:字典是无序的,而列表和元组是有序的,网上有关于有序字典的讨论]vars函数与此相似,它返回的是包含每个成员当前值的字典.如果你使用不带参数的vars,它将返回当前局部名称空间的可见元素(同locals()函数).如Example1-11所表示.
File:builtin-vars-example-1.pybook="library2"pages=250scripts=350print"the%(book)sbookcontainsmorethan%(scripts)sscripts"%vars()thelibrarybookcontainsmorethan350scripts1.2.4.检查对象类型Python是一种动态类型语言,这意味着给一个定变量名可以在不同的场合绑定到不同的类型上.在接下面例子中,同样的函数分别被整数,浮点数,以及一个字符串调用:
deffunction(value):printvaluefunction(1)function(1.0)function("one")type函数(如Example1-12所示)允许你检查一个变量的类型.这个函数会返回一个typedescriptor(类型描述符),它对于Python解释器提供的每个类型都是不同的.
File:builtin-type-example-1.pydefdump(value):printtype(value),valuedump(1)dump(1.0)dump("one")
File:builtin-type-example-2.pydefload(file):ifisinstance(file,type("")):file=open(file,"rb")returnfile.read()printlen(load("samples/sample.jpg")),"bytes"printlen(load(open("samples/sample.jpg","rb"))),"bytes"4672bytes4672bytescallable函数,如Example1-14所示,可以检查一个对象是否是可调用的(无论是直接调用或是通过apply).对于函数,方法,lambda函式,类,以及实现了__call__方法的类实例,它都返回True.
File:builtin-callable-example-1.pydefdump(function):ifcallable(function):printfunction,"iscallable"else:printfunction,"is*not*callable"classA:defmethod(self,value):returnvalueclassB(A):def__call__(self,value):returnvaluea=A()b=B()dump(0)#simpleobjectsdump("string")dump(callable)dump(dump)#functiondump(A)#classesdump(B)dump(B.method)dump(a)#instancesdump(b)dump(b.method)0is*not*callablestringis*not*callable
你可以在operator模块中找到检查对象是否为某一内建类型(数字,序列,或者字典等)的函数.但是,因为创建一个类很简单(比如实现基本序列方法的类),所以对这些类型使用显式的类型判断并不是好主意.
在处理类和实例的时候会复杂些.Python不会把类作为本质上的类型对待;相反地,所有的类都属于一个特殊的类类型(specialclasstype),所有的类实例属于一个特殊的实例类型(specialinstancetype).
File:builtin-isinstance-example-1.pyclassA:passclassB:passclassC(A):passclassD(A,B):passdefdump(object):printobject,"=>",ifisinstance(object,A):print"A",ifisinstance(object,B):print"B",ifisinstance(object,C):print"C",ifisinstance(object,D):print"D",printa=A()b=B()c=C()d=D()dump(a)dump(b)dump(c)dump(d)dump(0)dump("string")
注意,isinstance可以接受任何对象作为参数,而issubclass函数在接受非类对象参数时会引发TypeError异常.
File:builtin-issubclass-example-1.pyclassA:passclassB:passclassC(A):passclassD(A,B):passdefdump(object):printobject,"=>",ifissubclass(object,A):print"A",ifissubclass(object,B):print"B",ifissubclass(object,C):print"C",ifissubclass(object,D):print"D",printdump(A)dump(B)dump(C)dump(D)dump(0)dump("string")A=>AB=>BC=>ACD=>ABD0=>Traceback(innermostlast):File"builtin-issubclass-example-1.py",line29,inFile"builtin-issubclass-example-1.py",line15,indumpTypeError:argumentsmustbeclasses1.2.5.计算Python表达式Python提供了在程序中与解释器交互的多种方法.例如eval函数将一个字符串作为Python表达式求值.你可以传递一串文本,简单的表达式,或者使用内建Python函数.如Example1-17所示.
File:builtin-eval-example-2.pyprinteval("__import__('os').getcwd()")printeval("__import__('os').remove('file')")/home/fredrik/librarybookTraceback(innermostlast):File"builtin-eval-example-2",line2,inFile"
幸运地是,这个问题很容易解决.你可以给eval函数传递第2个参数,一个定义了该表达式求值时名称空间的字典.我们测试下,给函数传递个空字典:
>>>printeval("__import__('os').remove('file')",{})Traceback(innermostlast):File"
这是因为Python在求值前会检查这个字典,如果没有发现名称为__builtins__的变量(复数形式),它就会添加一个:
>>>namespace={}>>>printeval("__import__('os').remove('file')",namespace)Traceback(innermostlast):File"
[!Feather注:如果我RP不错的话,添加的这个__builtins__就是当前的__builtins__]我们注意到了如果这个变量存在,Python就不会去添加默认的,那么我们的解决方法也来了,为传递的字典参数加入一个__builtins__项即可.如Example1-19所示.
File:builtin-eval-example-3.pyprinteval("__import__('os').getcwd()",{})printeval("__import__('os').remove('file')",{"__builtins__":{}})/home/fredrik/librarybookTraceback(innermostlast):File"builtin-eval-example-3.py",line2,inFile"
eval函数只针对简单的表达式.如果要处理大块的代码,你应该使用compile和exec函数(如Example1-20所示).
File:builtin-compile-example-1.pyNAME="script.py"BODY="""prnt'owl-stretchingtime'"""try:compile(BODY,NAME,"exec")exceptSyntaxError,v:print"syntaxerror:",v,"in",NAME#syntaxerror:invalidsyntaxinscript.py成功执行后,compile函数会返回一个代码对象,你可以使用exec语句执行它,参见Example1-21.
File:builtin-compile-example-2.pyBODY="""print'theant,anintroduction'"""code=compile(BODY,"