l o g s是什么软件可以删除吗?

分享给朋友:通用代码: <input id="link4" type="text" class="form_input form_input_s" value="" />复 制flash地址: 复 制html代码: <input type="text" class="form_input form_input_s" id="link3" value="" />复 制分享视频到站外获取收益&&手机扫码分享视频二维码2小时内有效B e e n
S o L o n g下载至电脑扫码用手机看用或微信扫码在手机上继续观看二维码2小时内有效B e e n
S o L o n g扫码用手机继续看用或微信扫码在手机上继续观看二维码2小时内有效,扫码后可分享给好友没有优酷APP?立即下载请根据您的设备选择下载版本
药品服务许可证(京)-经营-请使用者仔细阅读优酷、、Copyright(C)2017 优酷
版权所有不良信息举报电话:[精彩] Python 指南 - ChinaUnix.net
[精彩] Python 指南
http://www.chinaunix.net 作者:&&发表于: 11:28:43
1.&开胃菜&
2.&使用Python解释器&
2.1&调用解释器&
2.1.1&传递参数&
2.1.2&交互模式&
2.2&解释器及其工作模式&
2.2.1&错误处理&
2.2.2&执行&Python&脚本&
2.2.3&源程序编码&
2.2.4&交互环境的启动文件&
3.初步认识&Python&
3.1&像使用计算器一样使用Python&
3.1.1&数值&
3.1.2&字符串&
3.1.3&Unicode&字符串&
3.1.4&链表&
3.2&开始编程&
4.&流程控制&
4.1&if&语法&
4.2&for&语法&
4.3&range()&函数&
4.4&break&和&continue&语法以及&else&子句&在循环中的用法&
4.5&pass&语法&
4.6&定义函数&
4.7&定义函数的进一步知识&
4.7.1&定义参数变量&
4.7.2&参数关键字&
4.7.3&可变参数表&
4.7.4&Lambda&形式&
4.7.5&文档字符串&
5.&数据结构&
5.1&深入链表&
5.1.1&将链表作为堆栈来使用&
5.1.2&将链表作为队列来使用&
5.1.3&函数化的编程工具&
5.1.4&链表的内含(Comprehensions)&
5.2&del&语法&
5.3&Tuples&和&Sequences&
5.4&字典(Dictionaries)&
5.5&循环技巧&
5.6&深入条件控制&
5.7&Sequences&和其它类型的比较&
6.1&深入模块&
6.1.1&模块搜索路径&
6.1.2&“编译”&Python&文件&
6.2&标准模块&
6.3&dir()&函数&
6.4.1&从包中导入所有内容(import&*&)&
6.4.2&隐式包引用&
6.4.3&包中的多重路径&
7.&输入和输出&
7.1&格式化输出&
7.2&读写文件&
7.2.1&文件对象的方法&
7.2.2&pickle&模块&
8.&错误和异常&
8.1&语法&Errors&
8.3&捕获异常&
8.4&释放异常&
8.5&用户自定义异常&
8.6&定义&Clean-up&Actions&
9.1&有关术语的话题&
9.2&Python&的作用域和命名空间&
9.3&初识类
9.3.1&类定义语法&
9.3.2&类对象&
9.3.3&实例对象&
9.3.4&方法对象&
9.4&一些说明&
9.5.1&多继承&
9.6&私有变量&
9.8&异常也是类&
9.9&迭代子(Iterators)&
9.10&发生器(Generators)&
10.&接下来?&
A.&交互式编辑和历史回溯&
A.1&行编辑&
A.2&历史回溯&
A.3&快捷键绑定&
B.&浮点计算:问题与极限&
B.1&表达错误&
C.&历史和授权&
C.1&本软件的历史&
C.2&修改和使用Python的条件(Terms&and&conditions&for&accessing&or&otherwise&using&Python)&
关于本文档
& 回复于: 16:44:08
前言
Copyright&&&,&2003&Python&Software&Foundation.&All&rights&reserved.&
Copyright&&&2000&.&All&rights&reserved.&
Copyright&&&&Corporation&for&National&Research&Initiatives.&All&rights&reserved.&
Copyright&&&&Stichting&Mathematisch&Centrum.&All&rights&reserved.&
See&the&end&of&this&document&for&complete&license&and&permissions&information.&
概要:
Python&是一种容易学习的强大语言。它包括了高效的高级数据结构,提供了一个简单但很有有效的方式以便进行面向对象编程。Python&优雅的语法,动态数据类型,以及它的解释器,使其成为了大多数平台上应用于各领域理想的脚本语言以及开发环境。&
Python解释器及其扩展标准库的源码和编译版本可以从Python的Web站点http://www.python.org/及其所有镜像站上免费获得,并且可以自由发布。该站点上也提供了Python的一些第三方模块,程序,工具,以及附加的文档。&
Python的解释器很容易通过C或C++(或者其它可以由C来调用的语言)来实现功能和数据结构的扩展。因些Python&也很适于做为定制应用的一种扩展语言。&
这个手册介绍了一些Python语言及其系统的基本知识与根念。这有助于对Python有一个基本的认识,当然所有的例子都包括在里面了,所以这本手册很适合离线阅读。&
需要有关标准对象和模块的详细介绍的话,请查询Python&程序库参考手册&文档。Python&参考手册&提供了更多的关于语言方面的正式说明。需要编写C或C++扩展,请阅读&Python&解释器的扩展和集成&以及Python/C&API&参考手册。这几本书涵盖了各个深度上的Python知识。&
本手册不会涵盖Python的所有功能,也不会去解释所用到的所有相关的知识。相反,它介绍了许多Python中最引人注目的功能,这会对读者掌握这门语言的风格大有帮助。读过它后,你应该可以阅读和编写Python模块和程序了,接下来你可以从Python&库参考手册中进一步学习Python复杂多变的库和模块了。
& 回复于: 16:44:42
1.&开胃菜
如果你写过大规模的Shell脚本,应该会有过这样的体会:你还非常想再加一些别的功能进去,但它已经太大、太慢、太复杂了;或者这个功能需要调用一个系统函数,或者它只适合通过C来调用……通常这些问题还不足以严肃到需要用C重写这个Shell;可能这个功能需要一些类似变长字符串或其它一些在Shell脚本中很容易找到的数据类型(比如文件名的有序列表),但它们用C来实现就要做大量的工作,或者,你对C还不是很熟悉。&
另一种情况:可能你需要使用几个C库来工作,通常C的编写/编译/测试/重编译周期太慢。你需要尽快的开发软件。也许你需要写一个使用扩展语言的程序,但不想设计一个语言,并为此编写调试一个解释器,然后再把它集成进你的程序。&
遇到以上情况,Python可能就是你要找的语言。Python很容易上手,但它是一门真正的编程语言,提供了比Shell多的多的结构,支持大型程序。另一方面,它提供了比C更多的错误检查,并且,做为一门高级语言,它拥有内置的高级数据类型,例如可变数组和字典,如果通过C来实现的话,这些工作可能让你大干上几天的时间。因为拥有更多的通用数据类型,Python适合比Awk甚至Perl更广泛的问题领域,在其它的很多领域,Python至少比别的语言要易用得多。&
Python可以让你把自己的程序分隔成不同的模块,这样就可以在其它的Python程序中重用。这样你就可以让自己的程序基于一个很大的标准模块集或者用它们做为示例来学习Python编程。Python中集成了一些类似文件I/O,系统调用,sockets,甚至像Tk这样的用户图形接口。&
Python是一门解释型语言,因为不需要编译和链接的时间,它可以帮你省下一些开发时间。解释器可以交互式使用,这样就可以很方便的测试语言中的各种功能,以便于编写发布用的程序,或者进行自下而上的开发。还可以当它是一个随手可用的计算器。&
Python可以写出很紧凑和可读性很强的程序。用Python写的程序通常比同样的C或C++程序要短得多,这是因为以下几个原因:&
高级数据结构使你可以在一个单独的语句中表达出很复杂的操作;&
语句的组织依赖于缩进而不是begin/end块;&
不需要变量或参数声明。&
Python是可执行的:如果你会用C语言写程序,那就可以很容易的为解释器添加新的集成模块和功能,或者优化瓶颈,使其达到最大速度,或者使Python能够链接到所需的二进制架构上(比如某个专用的商业图形库)。等你真正熟悉这一切了,你就可以把Python集成进由C写成的程序,把Python当做这个程序的扩展或命令行语言。&
顺便说一下,这个语言的名字来源于BBC的“Monty&Python's&Flying&Circus”节目,和凶猛的爬虫没有任何关系。在文档中引用Monty&Python典故不仅是允许的,而且还受到鼓励!&
现在你已经了解了Python中所有激动人心的东西,大概你想仔细的试试它了。学习一门语言最好的办法就是使用它,你会很乐于这样做。&
下一节中,我们会很机械的说明解释器的用法。这没有什么神秘的,不过有助于我们练习后面展示的例子。&
本指南其它部分通过例子介绍了Python语言和系统的各种功能,开始是简单表达式、语法和数据类型,接下来是函数和模块,最后是诸如异常和自定义类这样的高级内容。
& 回复于: 16:45:14
2.&使用Python解释器
&&
2.1&调用解释器
通常Python的解释器被安装在目标机器的&/usr/local/bin/python&目录下;把&/usr/local/bin&目录放进你的UNIX&Shell&的搜索路径里,确保它可以通过输入&
python
来启动。因为安装路径是可选的,所以也有可能安装在其它位置,你可以与安装Python的用户或系统管理员联系。(例如,/usr/local/python就是一个很常见的选择)&
输入一个文件结束符(UNIX上是Ctrl+D,Windwos上是Ctrl+Z)解释器会以0值退出(就是说,没有什么错误,正常退出--译者)。如果这没有起作用,你可以输入以下命令退出:“import&&sys.exit()”。&
解释器的行编辑功能并不很复杂。装在Unix上的解释器可能会有GNU&readline&库支持,这样就可以额外得到精巧的交互编辑和历史记录功能。可能检查命令行编辑器支持能力最方便的方式是在主提示符下输入Ctrl+P。如果有嘟嘟声(计算机扬声器),说明你可以使用命令行编辑功能,从附录&A&可以查到快捷键的介绍。如果什么也没有发声,或者P显示了出来,说明命令行编辑功能不可用,你只有用退格键删掉输入的命令了。
解释器的操作有些像Unix&Shell:使用终端设备做为标准输入来调用它时,解释器交互的解读和执行命令,通过文件名参数或以文件做为标准输入设备时,它从文件中解读并执行脚本。
启动解释器的第三个方法是“python&-c&command&[arg]&...”,这种方法可以在命令行中直接执行语句,等同于Shell的&-c选项。因为Python语句通常会包括空格之类的特殊字符,所以最好把整个语句用双引号包起来。
注意“python&file”和“python&&file”是有区别的。对于后一种情况,程序中类似于调用&input()&和raw_input()这样的输入请求,来自于确定的文件。因为在解析器开始执行之前,文件已经完全读入,所以程序指向文件尾。在前一种情况(这通常是你需要的)它们从来自于任何联接到Python解释器的标准输入,无论它们是文件还是其它设备。
使用脚本文件时,经常会运行脚本然后进入交互模式。这也可以通过在脚本之前加上-i参数来实现。(如果脚本来自标准输入,就不能这样运行,与前一段提到的原因一样。)
&&
2.1.1&参数传递&
调用解释器时,脚本名和附加参数之传入一个名为sys.argv的字符串列表。没有脚本和参数时,它至少也有一个元素:sys.argv[0]此时为空字符串。脚本名指定为‘&-&’(表示标准输入)时,sys.argv[0]被设置为‘&-&’,使用&-c&指令时,sys.argv[0]被设定为‘&-c&’。&-c&命令之后的参数不会被&Python&解释器的选项处理机制所截获,而是留在sys.argv&中,供脚本命令操作。
&&
2.1.2&交互模式&
从tty读取命令时,我们称解释器工作于交互模式。这种模式下它根据主提示符来执行,主提示符通常标识为三个大于号(“&;&;&;&”);继续的部分被称为从属提示符,由三个点标识(“...&”)。在第一行之前,解释器打印欢迎信息、版本号和授权提示:
python
Python&2.3&(#1,&Jul&30&:59)
[GCC&3.2&&(prerelease)]&on&cygwin
Type&"help",&"copyright",&"credits"&or&"license"&for&more&information.
&;&;&;
输入多行结构时需要从属提示符了,例如,下面这个&if&语句:
&;&;&;&the_world_is_flat&=&1
&;&;&;&if&the_world_is_flat:
...&&&&&print&"Be&careful&not&to&fall&off!"
...&
Be&careful&not&to&fall&off!
&&
2.2&解释器及其环境&
&&
2.2.1&错误处理&
有错误发生时,解释器打印一个错误信息和栈跟踪(监视)器?。交互模式下,它返回主提示符,如果从文件输入执行,它在打印栈跟踪器后以非零状态退出。(异常可以由try语句中的except子句来控制,这样就不会出现上文中的错误信息)有一些非常致命的错误会导致非零状态下退出,这由通常由内部矛盾和内存溢出造成。所有的错误信息都写入标准错误流;命令中执行的普通输出写入标准输出。
在主提示符或附属提示符输入中断符(通常是Control-C&or&DEL)就会取消当前输入,回到主命令行。2.1执行命令时输入一个中断符会抛出一个&KeyboardInterrupt&异常,它可以被try句截获。
&&
2.2.2&执行Python脚本&
BSD系统中,Python脚本可以像Shell脚本那样直接执行,只要在脚本文件开头写一行命令,指定文件和模式:
#!&/usr/bin/env&python
(将用户路径通知解释器)&“#!”必须是文件的前两个字符,在某些平台上,第一行必须以Unix风格的行结束符(“\n”)结束,不能用Mac(“\r”)或Windows(“\r\n”)的结束符。注意,“#”是Python中是行注释的起始符。
脚本可以通过&chmod&命令指定执行模式和许可权。
$&chmod&+x&myscript.py
2.2.3&源程序编码&
Python的源文件可以通过编码使用&ASCII&以外的字符集。&最好的做法是在&#!&行后面用一个特殊的注释行来定义字符集。
#&-*-&coding:&iso-8859-1&-*-
根据这个声明,Python会将文件中的字符尽可能的从指定的编码转为Unicode,在本例中,这个字符集是&iso-8859-1&。在&Python&库参考手册&中可以找到可用的编码列表(根据我的实验,中文似乎只能用cp-936或utf-8,不直接支持GB,GBK,GB-18030或ISO-10646--译者注)。
如果你的文件编辑器支持UTF-8格式,并且可以保存UTF-8标记(aka&BOM&-&Byte&Order&Mark),你可以用这个来代替编码声明(看来至少Jext还不支持这样做,而Vim,我还没找到它的编码设置在哪里,还是老老实实的用注释行指定源代码的编码吧--译者注)。IDLE可以通过设定Options/General/Default&Source&Encoding/UTF-8&来支持它。需要注意的是旧版Python不支持这个标记(Python&2.2或更早的版本),也同样不能使操作系统支持#!文件。
使用UTF-8内码(无论是用标记还是编码声明),我们可以在字符串和注释中使用世界上的大部分语言。标识符中不能使用非&ASCII&字符集。为了正确显示所有的字符,你一定要在编辑器中将文件保存为UTF-8格式,而且要使用支持文件中所有字符的字体。&
&&
2.2.4&交互式环境的启动文件&
使用Python解释器的时候,我们可能需要在每次解释器启动时执行一些命令。你可以在一个文件中包含你想要执行的命令,设定一个名为PYTHONSTARTUP&的环境变量来指定这个文件。这类似于Unix&shell的.profile文件。
这个文件在交互会话期是只读的,当Python从脚本中解读文件或以终端做为外部命令源时则不会如此(尽管它们的行为很像是处在交互会话期。)它与解释器执行的命令处在同一个命名空间,所以由它定义或引用的一切可以在解释器中不受限制的使用。你也可以在这个文件中改变sys.ps1和sys.ps2指令。
如果你想要在当前目录中执行附加的启动文件,你可以在全局启动文件中加入类似以下的代码:“if&os.path.isfile('.pythonrc.py'):&execfile('.pythonrc.py')”。&如果你想要在某个脚本中使用启动文件,必须要在脚本中写入这样的语句:
import&os
filename&=&os.environ.get('PYTHONSTARTUP')
if&filename&and&os.path.isfile(filename):
&&&&execfile(filename)
& 回复于: 16:45:53
3.&Python的非正式介绍
在后面的例子中,区分输入和输出的方法是看是否有提示符(“&;&;&;&”和“..&”):想要重复这些例子的话,你就要在提示符显示后输入所有的一切;没有以提示符开始的行,是解释器输出的信息。需要注意的是示例中的从属提示符用于多行命令的结束,它表示你需要输入一个空行。
本手册中的很多示例都包括注释,甚至有一些在交互提示符中折行。Python中的注释以符号“#”起始,一直到当前行的结尾。注释可能出现在一行的开始,也可能跟在空格或程序代码之后,但不会出现在字符串中,字符串中的#号只代表#号。
#&this&is&the&first&comment
SPAM&=&1&&&&&&&&&&&&&&&&&#&and&this&is&the&second&comment
&&&&&&&&&&&&&&&&&&&&&&&&&#&...&and&now&a&third!
STRING&=&"#&This&is&not&a&comment."
&&
3.1&初步认识Python&
让我们试验一些简单的Python命令。启动解释器然后等待主提示符“&;&;&;&”出现(这用不了太久)。
&&
3.1.1&数值&
解释器的行为就像是一个计算器。你可以向它输入一个表达式,它会返回结果。表达式的语法简明易懂:+,-,*,/和大多数语言中的用法一样(比如C或Pascal),括号用于分组。例如:
&;&;&;&2+2
4
&;&;&;&#&This&is&a&comment
...&2+2
4
&;&;&;&2+2&&#&and&a&comment&on&the&same&line&as&code
4
&;&;&;&(50-5*6)/4
5
&;&;&;&#&Integer&division&returns&the&floor:
...&7/3
2
&;&;&;&7/-3
-3
像c一样,等号(“=”)用于给变量赋值。被分配的值是只读的。
&;&;&;&width&=&20
&;&;&;&height&=&5*9
&;&;&;&width&*&height
900
同一个值可以同时赋给几个变量:
&;&;&;&x&=&y&=&z&=&0&&#&Zero&x,&y&and&z
&;&;&;&x
0
&;&;&;&y
0
&;&;&;&z
0
Python完全支持浮点数,不同类型的操作数混在一起时,操作符会把整型转化为浮点数。
&;&;&;&3&*&3.75&/&1.5
7.5
&;&;&;&7.0&/&2
3.5
复数也同样得到了支持,虚部由一个后缀“j”或者“J”来表示。带有非零实部的复数记为“(real+imagj)”,或者也可以通过“complex(real,&imag)”函数创建。
&;&;&;&1j&*&1J
(-1+0j)
&;&;&;&1j&*&complex(0,1)
(-1+0j)
&;&;&;&3+1j*3
(3+3j)
&;&;&;&(3+1j)*3
(9+3j)
&;&;&;&(1+2j)/(1+1j)
(1.5+0.5j)
复数总是由实部和虚部两部分浮点数来表示。可能从&z.real&和&z.imag&得到复数z的实部和虚部。
&;&;&;&a=1.5+0.5j
&;&;&;&a.real
1.5
&;&;&;&a.imag
0.5
用于向浮点数和整型转化的函数(float(),&int()&和&long())不能对复数起作用--没有什么方法可以将复数转化为实数。可以使用abs(z)取得它的模,也可以通过z.real得到它的实部。
&;&;&;&a=3.0+4.0j
&;&;&;&float(a)
Traceback&(most&recent&call&last):
&&File&"&stdin&;",&line&1,&in&?
TypeError:&can't&convert&complex&to&&use&e.g.&abs(z)
&;&;&;&a.real
3.0
&;&;&;&a.imag
4.0
&;&;&;&abs(a)&&#&sqrt(a.real**2&+&a.imag**2)
5.0
&;&;&;
交互模式下,最近一次表达式输出保存在_变量中。这意味着把Python当做桌面计算器使用时,它可以更容易的进行连续计算,例如:
&;&;&;&tax&=&12.5&/&100
&;&;&;&price&=&100.50
&;&;&;&price&*&tax
12.5625
&;&;&;&price&+&_
113.0625
&;&;&;&round(_,&2)
113.06
&;&;&;
这个变量对于用户来说是只读的。不要试图去给它赋值--由于Python的语法效果,你只会创建一个同名的局部变量覆盖它。
&&
3.1.2&字符串
除了数值,Python还可以通过几种不同的方法操作字符串。字符串用单引号或双引号标识:
&;&;&;&'spam&eggs'
'spam&eggs'
&;&;&;&'doesn\'t'
"doesn't"
&;&;&;&"doesn't"
"doesn't"
&;&;&;&'"Yes,"&he&said.'
'"Yes,"&he&said.'
&;&;&;&"\"Yes,\"&he&said."
'"Yes,"&he&said.'
&;&;&;&'"Isn\'t,"&she&said.'
'"Isn\'t,"&she&said.'
字符串可以通过几种方式分行。可以在行加反斜杠做为继续符,这表示下一行是当前行的逻辑沿续。
hello&=&"This&is&a&rather&long&string&containing\n\
several&lines&of&text&just&as&you&would&do&in&C.\n\
&&&&Note&that&whitespace&at&the&beginning&of&the&line&is\
&significant."
print&hello
注意换行用&\n&来表示;反斜杠后面的新行标识(newline,缩写“n”)会转换为换行符,示例会按如下格式打印:
This&is&a&rather&long&string&containing
several&lines&of&text&just&as&you&would&do&in&C.
&&&&Note&that&whitespace&at&the&beginning&of&the&line&is&significant.
然而,如果我们创建一个“raw”行,\n序列就不会转为换行,示例源码最后的反斜杠和换行符n都会做为字符串中的数据处理。如下所示:
hello&=&r"This&is&a&rather&long&string&containing\n\
several&lines&of&text&much&as&you&would&do&in&C."
print&hello
会打印为:
This&is&a&rather&long&string&containing\n\
several&lines&of&text&much&as&you&would&do&in&C.
或者,字符串可以用一对三重引号”””或'''来标识。三重引号中的字符串在行尾不需要换行标记,所有的格式都会包括在字符串中。
print&"""
Usage:&thingy&[OPTIONS]&
&&&&&-h&&&&&&&&&&&&&&&&&&&&&&&&Display&this&usage&message
&&&&&-H&hostname&&&&&&&&&&&&&&&Hostname&to&connect&to
"""
produces&the&following&output:&
Usage:&thingy&[OPTIONS]&
&&&&&-h&&&&&&&&&&&&&&&&&&&&&&&&Display&this&usage&message
&&&&&-H&hostname&&&&&&&&&&&&&&&Hostname&to&connect&to
解释器打印出来的字符串与它们输入的形式完全相同:内部的引号,用反斜杠标识的引号和各种怪字符,都精确的显示出来。如果字符串中包含单引号,不包含双引号,可以用双引号引用它,反之可以用单引号。(后面介绍的print语句,可以可以用来写没有引号和反斜杠的字符串)。
字符串可以用+号联接(或者说粘合),也可以用*号循环。
&;&;&;&word&=&'Help'&+&'A'
&;&;&;&word
'HelpA'
&;&;&;&'&'&+&word*5&+&'&;'
'&HelpAHelpAHelpAHelpAHelpA&;'
两个字符串值之间的联接是自动的,上例第一行可以写成“word&=&'Help'&'A'”这种方式只对字符串值有效,任何字符串表达式都不适用这种方法。
&;&;&;&import&string
&;&;&;&'str'&'ing'&&&&&&&&&&&&&&&&&&&#&&&-&&This&is&ok
'string'
&;&;&;&string.strip('str')&+&'ing'&&&#&&&-&&This&is&ok
'string'
&;&;&;&string.strip('str')&'ing'&&&&&#&&&-&&This&is&invalid
&&File&"&stdin&;",&line&1,&in&?
&&&&string.strip('str')&'ing'
&&&&&&&&&&&&&&&&&&&&&&&&&&&&^
SyntaxError:&invalid&syntax
字符串可以用下标(索引)查询;就像C一样,字符串的第一个字符下标是0。这里没有独立的字符类型,字符仅仅是大小为一的字符串。就像在Icon中那样,字符串的子串可以通过切片标志来表示:两个由冒号隔开的索引。
&;&;&;&word[4]
'A'
&;&;&;&word[0]
'He'
&;&;&;&word[2]
'lp'
切片索引可以使用默认值;省略前一个索引表示0,省略后一个索引表示被切片的字符串的长度。
&;&;&;&word[]&&&&#&The&first&two&characters
'He'
&;&;&;&word[2:]&&&&#&All&but&the&first&two&characters
'lpA'
和C字符串不同,Python字符串不能改写。按字符串索引赋值会产生错误。
&;&;&;&word[0]&=&'x'
Traceback&(most&recent&call&last):
&&File&"&stdin&;",&line&1,&in&?
TypeError:&object&doesn't&support&item&assignment
&;&;&;&word[]&=&'Splat'
Traceback&(most&recent&call&last):
&&File&"&stdin&;",&line&1,&in&?
TypeError:&object&doesn't&support&slice&assignment
然而,可以通过简单有效的组合方式生成新的字符串:
&;&;&;&'x'&+&word[1:]
'xelpA'
&;&;&;&'Splat'&+&word[4]
'SplatA'
切片操作有一个很有用的不变性:&s[]&+&s[i:]&等于s。
&;&;&;&word[]&+&word[2:]
'HelpA'
&;&;&;&word[]&+&word[3:]
'HelpA'
退化的切片索引被处理的很优美:过大的索引代替为字符串大小,下界比上界大的返回空字符串。
&;&;&;&word[1]
'elpA'
&;&;&;&word[10:]
''
&;&;&;&word[2]
''
索引可以是负数,计数从右边开始,例如:
&;&;&;&word[-1]&&&&&#&The&last&character
'A'
&;&;&;&word[-2]&&&&&#&The&last-but-one&character
'p'
&;&;&;&word[-2:]&&&&#&The&last&two&characters
'pA'
&;&;&;&word[:-2]&&&&#&All&but&the&last&two&characters
'Hel'
不过-0还是0,所以它不是从右边计数的!
&;&;&;&word[-0]&&&&&#&(since&-0&equals&0)
'H'
越界的负切片索引会被截断,不过不要尝试在前元素索引(非切片的)中这样做:
&;&;&;&word[-100:]
'HelpA'
&;&;&;&word[-10]&&&&#&error
Traceback&(most&recent&call&last):
&&File&"&stdin&;",&line&1,&in&?
IndexError:&string&index&out&of&range
理解切片的最好方式是把索引视为两个字符之间的点,第一个字符的左边是0,字符串中第n个字符的右边是索引n,例如:
&+---+---+---+---+---+&
&|&H&|&e&|&l&|&p&|&A&|
&+---+---+---+---+---+&
&0&&&1&&&2&&&3&&&4&&&5&
-5&&-4&&-3&&-2&&-1
第一行是字符串中给定的0到5各个索引的位置,第二行是对应的负索引。从i到j的切片由这两个标志之间的字符组成。
对于非负索引,切片长度就是两索引的差。例如,word[1]的长度是2。
内置函数&len()&返回字符串长度:
&;&;&;&s&=&'supercalifragilisticexpialidocious'
&;&;&;&len(s)
34
&&
3.1.3&Unicode&字符串
从Python2.0开始,程序员们可以使用一种新的数据类型来存储文本数据:Unicode&对象。它可以用于存储多种Unicode数据(请参阅&http://www.unicode.org/&),并且,通过必要时的自动转换,它可以与现有的字符串对象良好的结合。
Unicode针对现代和旧式的文本中所有的字符提供了一个序列。以前,字符只能使用256个序号,文本通常通过绑定代码页来与字符映射。这很容易导致混乱,特别是软件的国际化(internationalization--通常写做“i18n”--“i”+18&characters&+“n”)。Unicode通过为所有字符定义一个统一的代码页解决了这个问题。
Python中定义一个Unicode字符串和定义一个普通字符串一样简单:
&;&;&;&u'Hello&World&!'
u'Hello&World&!'
引号前小写的“u”表示这里创建的是一个Unicode字符串。如果你想加入一个特殊字符,可以使用Python的&Unicode-Escape&编码。如下例所示:
&;&;&;&u'Hello\u0020World&!'
u'Hello&World&!'
被替换的&\u0020&标识表示在给定位置插入编码值为&0x0020&的&Unicode字符(空格符)。
其它字符也会被直接解释成对应的Unicode码。如果你有一个在西方国家常用的Latin-1编码字符串,你可以发现Unicode字符集的前256个字符与Lation-1的对应字符编码完全相同。
另外,有一种与普通字符串相同的行模式。想要使用Python的Raw-Unicode-Escape&编码,你需要在字符串的引号前加上&ur&前缀。如果在小写“u”前可能有不止一个反斜杠,它只会把那些单独的&\uXXXX&转化为Unicode字符。
&;&;&;&ur'Hello\u0020World&!'
u'Hello&World&!'
&;&;&;&ur'Hello\\u0020World&!'
u'Hello\\\\u0020World&!'
行模式在你需要输入很多个反斜杠时很有用,可能会用于正规表达式。
作为这些编码标准的一部分,Python提供了一个完备的方法集用于从已知的编码集创建Unicode字符串。
内置函数unicode()&提供了访问(编码和解码)所有已注册的Unicode编码的方法。它能转换众所周知的&Latin-1,&ASCII,&UTF-8,&和&UTF-16。后面的两个可变长编码字符集用一个或多个byte存储Unicode字符。默认的字符集是&ASCII&,它只处理0到127的编码,拒绝其它的字符并返回一个错误。当一个Unicode字符串被打印、写入文件或通过str()转化时,它们被替换为默认的编码。
&;&;&;&u"abc"
u'abc'
&;&;&;&str(u"abc")
'abc'
&;&;&;&u"&&ü"
u'\xe4\xf6\xfc'
&;&;&;&str(u"&&ü")
Traceback&(most&recent&call&last):
&&File&"&stdin&;",&line&1,&in&?
UnicodeEncodeError:&'ascii'&codec&can't&encode&characters&in&position&0-2:&ordinal&not&in&range(128)
要把一个Unicode字符串用指定的字符集转化成8位字符串,可以使用Unicode对象提供的encode()方法,它有一个参数用以指定编码名称。编码名称小写。
&;&;&;&u"&&ü".encode('utf-8')
'\xc3\xa4\xc3\xb6\xc3\xbc'
如果你有一个特定编码的字符串,想要把它转为Unicode字符集,,可以使用uncode()函数,它以编码名做为第二个参数。
&;&;&;&unicode('\xc3\xa4\xc3\xb6\xc3\xbc',&'utf-8')
u'\xe4\xf6\xfc'
&&
3.1.4&链表
Python&已经有了几个复合数据类型,用于组织其它的值。最通用的是链表,它写为中括之间用逗号分隔的一列值(子项),链表的子项不一定是同一类型的值。
&;&;&;&a&=&['spam',&'eggs',&100,&1234]
&;&;&;&a
['spam',&'eggs',&100,&1234]
像字符串一样,链表也以零开始,可以被切片,联接,等等:
&;&;&;&a[0]
'spam'
&;&;&;&a[3]
1234
&;&;&;&a[-2]
100
&;&;&;&a[1:-1]
['eggs',&100]
&;&;&;&a[]&+&['bacon',&2*2]
['spam',&'eggs',&'bacon',&4]
&;&;&;&3*a[]&+&['Boe!']
['spam',&'eggs',&100,&'spam',&'eggs',&100,&'spam',&'eggs',&100,&'Boe!']
与不变的字符串不同,链表可以改变每个独立元素的值:
&;&;&;&a
['spam',&'eggs',&100,&1234]
&;&;&;&a[2]&=&a[2]&+&23
&;&;&;&a
['spam',&'eggs',&123,&1234]
可以进行切片操作,甚至还可以改变链表的大小:
&;&;&;&#&Replace&some&items:
...&a[0]&=&[1,&12]
&;&;&;&a
[1,&12,&123,&1234]
&;&;&;&#&Remove&some:
...&a[0]&=&[]
&;&;&;&a
[123,&1234]
&;&;&;&#&Insert&some:
...&a[1]&=&['bletch',&'xyzzy']
&;&;&;&a
[123,&'bletch',&'xyzzy',&1234]
&;&;&;&a[]&=&a&&&&&#&Insert&(a&copy&of)&itself&at&the&beginning
&;&;&;&a
[123,&'bletch',&'xyzzy',&,&'bletch',&'xyzzy',&1234]
内置函数len()也同样可以用于链表:
&;&;&;&len(a)
8
它也可以嵌套链表(在链表中创建其它链表),例如:
&;&;&;&q&=&[2,&3]
&;&;&;&p&=&[1,&q,&4]
&;&;&;&len(p)
3
&;&;&;&p[1]
[2,&3]
&;&;&;&p[1][0]
2
&;&;&;&p[1].append('xtra')&&&&&#&See&section&5.1
&;&;&;&p
[1,&[2,&3,&'xtra'],&4]
&;&;&;&q
[2,&3,&'xtra']
注意最后一个例子,p[1]和q实际上指向同一个对象!我们在后面会讲到对象语法。
&&
3.2&开始编程
当然,我们可以用Python做比2加2更复杂的事。例如,我们可以用以下的方法输出菲波那契(Fibonacci)序列的子序列:
&;&;&;&#&Fibonacci&series:
...&#&the&sum&of&two&elements&defines&the&next
...&a,&b&=&0,&1
&;&;&;&while&b&&&10:
...&&&&&&&print&b
...&&&&&&&a,&b&=&b,&a+b
...&
1
1
2
3
5
8
示例中介绍了一些新功能:
第一行包括了复合参数:变量a和b同时被赋值为0和1。最后一行又一次使用了这种技术,证明了在赋值之前表达式右边先进行了运算。右边的表达式从左到右运算。
while循环运行在条件为真时执行。在Python中,类似于C任何非零值为真,零为假。&这个条件也可以用于字符串或链表,事实上于对任何序列类型,长度非零时为真,空序列为假。示例所用的是一个简单的比较。标准的比较运算符写法和C相同:&&&(小于),&;&(大于),==&(等于),&=&(小于等于),&;=(大于等于)和!=&(不等于)。
循环体是缩进的:缩进是Python对语句分组的方法。&Python仍没有提供一个智能编辑功能所以你要在每一个缩进行输入一个tab或(一个或多个)空格。&实际上你可能会准备更为复杂的文本编辑器来编写你的Python程序,大多数文本编辑器都提供了自动缩进功能。交互式的输入一个复杂语句时,需要用一个空行表示完成(因为解释器没办法猜出你什么时候输入最后一行)。需要注意的是每一行都要有相同的空字符来标识这是同一个语句块。
print语句打印给定表达式的值。它与你仅仅输入你需要的表达式(就像前面的计算器示例)不同,它可以同时输出多个表达式。字符串输出时没有引号,各项之间用一个空格分开,你可以很容易区分它们,如下所示:
&;&;&;&i&=&256*256
&;&;&;&print&'The&value&of&i&is',&i
The&value&of&i&is&65536
print语句末尾的逗号避免了输出中的换行:
&;&;&;&a,&b&=&0,&1
&;&;&;&while&b&&&1000:
...&&&&&print&b,
...&&&&&a,&b&=&b,&a+b
...&
1&1&2&3&5&8&13&21&34&55&89&144&233&377&610&987
需要注意的是,如果最后一行仍没有写完,解释器会在它打印下一个命令时插入一个新行。
& 回复于: 16:49:23
4.&其它流程控制工具&
除了前面介绍的&while&语句,Python&还从别的语言中借鉴了一些流程控制功能,并有所改变。
&&
4.1&if&语句&
也许最有句的语句类型是&if&语句。例如:
&;&;&;&x&=&int(raw_input("Please&enter&an&integer:&"))
&;&;&;&if&x&&&0:
...&&&&&&x&=&0
...&&&&&&print&'Negative&changed&to&zero'
...&elif&x&==&0:
...&&&&&&print&'Zero'
...&elif&x&==&1:
...&&&&&&print&'Single'
...&else:
...&&&&&&print&'More'
...
可能会有&0&或很多个&elif&部分,else&是可选的。关键字“elif&”&是“&else&if&”的缩写,这个可以有效避免过深的缩进。if&...&elif&...&elif&...&序列用于替代其它语言中的&switch&或&case&语句。
& 回复于: 16:51:21
您的帖子中有论坛禁止发表的词汇或内容!
& 回复于: 16:52:12
4.3&range()&函数&
如果你需要一个数值序列,内置函数range()可能会很有用,它生成一个等差级数链表。
&;&;&;&range(10)
[0,&1,&2,&3,&4,&5,&6,&7,&8,&9]
range(10)生成了一个包含10个值的链表,它准确的用链表的索引值填充了这个长度为10的列表,所生成的链表中不包括范围中的结束值。也可以让range操作从另一个数值开始,或者可以指定一个不同的步进值(甚至是负数,有时这也被称为“步长”):
&;&;&;&range(5,&10)
[5,&6,&7,&8,&9]
&;&;&;&range(0,&10,&3)
[0,&3,&6,&9]
&;&;&;&range(-10,&-100,&-30)
[-10,&-40,&-70]
需要迭代链表索引的话,如下所示结合使用range()和len():
&;&;&;&a&=&['Mary',&'had',&'a',&'little',&'lamb']
&;&;&;&for&i&in&range(len(a)):
...&&&&&print&i,&a
...&
0&Mary
1&had
2&a
3&little
4&lamb
& 回复于: 16:52:43
4.4&break&和&continue&语句,&以及循环中的&else&子句
break语句和C中的类似,用于跳出最近的一级for或while循环。
continue&语句是从C中借鉴来的,它表示循环继续执行下一次迭代。
循环可以有一个else子句;它在循环迭代完整个列表(对于for)或执行条件为false(对于while)时执行,但循环被break中止的情况下不会执行。以下搜索素数的示例程序演示了这个子句:
&;&;&;&for&n&in&range(2,&10):
...&&&&&for&x&in&range(2,&n):
...&&&&&&&&&if&n&%&x&==&0:
...&&&&&&&&&&&&print&n,&'equals',&x,&'*',&n/x
...&&&&&&&&&&&&break
...&&&&&else:
...&&&&&&&&&&#&loop&fell&through&without&finding&a&factor
...&&&&&&&&&&print&n,&'is&a&prime&number'
...&
2&is&a&prime&number
3&is&a&prime&number
4&equals&2&*&2
5&is&a&prime&number
6&equals&2&*&3
7&is&a&prime&number
8&equals&2&*&4
9&equals&3&*&3
&&
4.5&pass&语句&
pass&语句什么也不做。它用于那些语法上必须要有什么语句,但程序上什么也不要做的场合,例如:
&;&;&;&while&True:
...&&&&&&&pass&#&Busy-wait&for&keyboard&interrupt
...
& 回复于: 16:54:01
4.6&定义函数&
我们可以编写一个函数来生成有给定上界的菲波那契数列:
&;&;&;&def&fib(n):&&&&#&write&Fibonacci&series&up&to&n
...&&&&&"""Print&a&Fibonacci&series&up&to&n."""
...&&&&&a,&b&=&0,&1
...&&&&&while&b&&&n:
...&&&&&&&&&print&b,
...&&&&&&&&&a,&b&=&b,&a+b
...&
&;&;&;&#&Now&call&the&function&we&just&defined:
...&fib(2000)
1&1&2&3&5&8&13&21&34&55&89&144&233&377&610&987&1597
关键字def&引入了一个函数定义。在其后必须跟有函数名和包括形式参数的圆括号。函数体语句从下一行开始,必须是缩进的。函数体的第一行可以是一个字符串值,这个字符串是该函数的&文档字符串,也可称作docstring。&&
有些文档字符串工具可以在线处理或打印文档,或让用户交互的浏览代码;在你的代码中加入文档字符串是一个好的作法,应该养成习惯。
调用函数时会为局部变量引入一个新的符号表。所有的局部变量都存储在这个局部符号表中。引用参数时,会先从局部符号表中查找,然后是全局符号表,然后是内置命名表。因此,全局参数虽然可以被引用,但它们不能在函数中直接赋值(除非它们用global语句命名)。
函数引用的实际参数在函数调用时引入局部符号表,因此,实参总是传值调用(这里的值总是一个对象引用,而不是该对象的值)。4.1&一个函数被另一个函数调用时,一个新的局部符号表在调用过程中被创建。
函数定义在当前符号表中引入函数名。作为用户定义函数,函数名有一个为解释器认可的类型值。这个值可以赋给其它命名,使其能句做为一个函数来使用。这就像一个重命名机制:
&;&;&;&fib
&function&object&at&10042ed0&;
&;&;&;&f&=&fib
&;&;&;&f(100)
1&1&2&3&5&8&13&21&34&55&89
你可能认为fib不是一个函数(function),而是一个过程(procedure)。Python和C一样,过程只是一个没有返回值的函数。实际上,从技术上讲,过程也有一个返回值,虽然是一个不讨人喜欢的。这个值被称为&None&(这是一个内置命名)。如果一个值只是None的话,通常解释器不会写一个None出来,如果你真想要看它的话,可以这样做:
&;&;&;&print&fib(0)
None
以下示列演示了如何从函数中返回一个包含菲波那契数列的数值链表,而不是打印它:
&;&;&;&def&fib2(n):&#&return&Fibonacci&series&up&to&n
...&&&&&"""Return&a&list&containing&the&Fibonacci&series&up&to&n."""
...&&&&&result&=&[]
...&&&&&a,&b&=&0,&1
...&&&&&while&b&&&n:
...&&&&&&&&&result.append(b)&&&&#&see&below
...&&&&&&&&&a,&b&=&b,&a+b
...&&&&&return&result
...&
&;&;&;&f100&=&fib2(100)&&&&#&call&it
&;&;&;&f100&&&&&&&&&&&&&&&&#&write&the&result
[1,&1,&2,&3,&5,&8,&13,&21,&34,&55,&89]
和以前一样,这个例子演示了一些新的Python功能:
& 回复于: 16:54:44
4.7&深入函数定义
有时需要定义参数个数可变的函数。有三个方法可以做到,我们可以组合使用它们。
&&
4.7.1&参数默认值&
最有用的形式是给一个或多个参数指定默认值。这样创建的函数可以在调用时使用更少的参数。
def&ask_ok(prompt,&retries=4,&complaint='Yes&or&no,&please!'):
&&&&while&True:
&&&&&&&&ok&=&raw_input(prompt)
&&&&&&&&if&ok&in&('y',&'ye',&'yes'):&return&1
&&&&&&&&if&ok&in&('n',&'no',&'nop',&'nope'):&return&0
&&&&&&&&retries&=&retries&-&1
&&&&&&&&if&retries&&&0:&raise&IOError,&'refusenik&user'
&&&&&&&&print&complaint
这个函数还可以用以下的方式调用:ask_ok('Do&you&really&want&to&quit?'),或者像这样:ask_ok('OK&to&overwrite&the&file?',&2)。
默认值在函数定义段被解析,如下所示:
def&f(arg=i):
&&&&print&arg
i&=&6
f()
will&print&5.&
重要警告:默认值只会解析一次。当默认值是一个可变对象,诸如链表、字典或大部分类实例时,会产生一些差异。例如,以下函数在后继的调用中会积累它的参数值:
def&f(a,&L=[]):
&&&&L.append(a)
&&&&return&L
print&f(1)
print&f(2)
print&f(3)
这会打印出:
[1]
[1,&2]
[1,&2,&3]
如果你不想在不同的函数调用之间共享参数默认值,可以如下面的实例一样编写函数:
def&f(a,&L=None):
&&&&if&L&is&None:
&&&&&&&&L&=&[]
&&&&L.append(a)
&&&&return&L
&&
4.7.2&参数关键字&
函数可以通过参数关键字的形式来调用,形如“keyword&=&value”。例如,以下的函数:
def&parrot(voltage,&state='a&stiff',&action='voom',&type='Norwegian&Blue'):
&&&&print&"--&This&parrot&wouldn't",&action,
&&&&print&"if&you&put",&voltage,&"Volts&through&it."
&&&&print&"--&Lovely&plumage,&the",&type
&&&&print&"--&It's",&state,&"!"
可以用以下的任一方法调用:
parrot(1000)
parrot(action&=&'VOOOOOM',&voltage&=&1000000)
parrot('a&thousand',&state&=&'pushing&up&the&daisies')
parrot('a&million',&'bereft&of&life',&'jump')
不过以下几种调用是无效的:
parrot()&&&&&&&&&&&&&&&&&&&&&#&required&argument&missing(缺少必要参数)
parrot(voltage=5.0,&'dead')&&#&non-keyword&argument&following&keyword(在关键字后面有非关键字参数)
parrot(110,&voltage=220)&&&&&#&duplicate&value&for&argument(对参数进行了重复赋值)
parrot(actor='John&Cleese')&&#&unknown&keyword(未知关键字)
通常,参数列表中的每一个关键字都必须来自于形式参数,每个参数都有对应的关键字。形式参数有没有默认值并不重要。实际参数不能一次赋多个值--形式参数不能在同一次调用中同时使用位置和关键字绑定值。这里有一个例子演示了在这种约束下所出现的失败情况:
&;&;&;&def&function(a):
...&&&&&pass
...&
&;&;&;&function(0,&a=0)
Traceback&(most&recent&call&last):
&&File&"&stdin&;",&line&1,&in&?
TypeError:&function()&got&multiple&values&for&keyword&argument&'a'
引入一个形如&**name&的参数时,它接收一个字典,该字典包含了所有未出现在形式参数列表中的关键字参数。这里可能还会组合使用一个形如&*name&的形式参数,它接收一个拓扑(下一节中会详细介绍),包含了所有没有出现在形式参数列表中的参数值。(*name&必须在&**name&之前出现)&例如,我们这样定义一个函数:
def&cheeseshop(kind,&*arguments,&**keywords):
&&&&print&"--&Do&you&have&any",&kind,&'?'
&&&&print&"--&I'm&sorry,&we're&all&out&of",&kind
&&&&for&arg&in&arguments:&print&arg
&&&&print&'-'*40
&&&&keys&=&keywords.keys()
&&&&keys.sort()
&&&&for&kw&in&keys:&print&kw,&':',&keywords[kw]
它可以像这样调用:
cheeseshop('Limburger',&"It's&very&runny,&sir.",
&&&&&&&&&&&"It's&really&very,&VERY&runny,&sir.",
&&&&&&&&&&&client='John&Cleese',
&&&&&&&&&&&shopkeeper='Michael&Palin',
&&&&&&&&&&&sketch='Cheese&Shop&Sketch')
当然它会按如下内容打印:
--&Do&you&have&any&Limburger&?
--&I'm&sorry,&we're&all&out&of&Limburger
It's&very&runny,&sir.
It's&really&very,&VERY&runny,&sir.
----------------------------------------
client&:&John&Cleese
shopkeeper&:&Michael&Palin
sketch&:&Cheese&Shop&Sketch
注意sort()方法在关键字字典内容打印前被调用,否则的话,打印参数时的顺序是未定义的。
&&
4.7.3&可变参数表
最后,一个最不常用的选择是可以让函数调用可变个数的参数。这些参数被包装进一个拓扑。在这些可变个数的参数之前,可以有零到多个普通的参数:
def&fprintf(file,&format,&*args):
&&&&file.write(format&%&args)
&&
4.7.4&Lambda&形式
出于适当的需要,有几种通常在功能性语言和Lisp中出现的功能加入到了Python。通过lambda关键字,可以创建很小的匿名函数。这里有一个函数返回它的两个参数的和:“lambda&a,&b:&a+b”。&Lambda&形式可以用于任何需要的函数对象。出于语法限制,它们只能有一个单独的表达式。语义上讲,它们只是普通函数定义中的一个语法技巧。类似于嵌套函数定义,lambda形式可以从包含范围内引用变量:
&;&;&;&def&make_incrementor(n):
...&&&&&return&lambda&x:&x&+&n
...
&;&;&;&f&=&make_incrementor(42)
&;&;&;&f(0)
42
&;&;&;&f(1)
43
&&
4.7.5&文档字符串&
这里介绍文档字符串的概念和格式。
第一行应该是关于对象用途的简介。简短起见,不用明确的陈述对象名或类型,因为它们可以从别的途径了解到(除非这个名字碰巧就是描述这个函数操作的动词)。这一行应该以大写字母开头,以句号结尾。
如果文档字符串有多行,第二行应该空出来,与接下来的详细描述明确分隔。接下来的文档应该有一或多段描述对象的调用约定、边界效应等。
Python的解释器不会从多行的文档字符串中去除缩进,所以必要的时候应当自己清除缩进。这符合通常的习惯。第一行之后的第一个非空行决定了整个文档的缩进格式。(我们不用第一行是因为它通常紧靠着起始的引号,缩进格式显示的不清楚。)留白“相当于”是字符串的起始缩进。每一行都不应该有缩进,如果有缩进的话,所有的留白都应该清除掉。相当于留白就是验证后的制表符扩展(通常是8个空格)。(这一段译得不通,有疑问的读者请参见原文--译者)
以下是一个多行文档字符串的示例:&
&;&;&;&def&my_function():
...&&&&&"""Do&nothing,&but&document&it.
...&
...&&&&&No,&really,&it&doesn't&do&anything.
...&&&&&"""
...&&&&&pass
...&
&;&;&;&print&my_function.__doc__
Do&nothing,&but&document&it.
&&&&No,&really,&it&doesn't&do&anything.
& 回复于: 16:55:20
5.&数据结构
本章节深入讲述一些你已经学习过的东西,并且还加入了新的内容。
&&
5.1&深入链表
链表类型有很多方法,这里是链表类型的所有方法:
append(
&x)
&
把一个元素添加到链表的结尾,相当于&a[len(a):]&=&[x]。
extend(
&L)
&
通过添加指定链表的所有元素来扩充链表,相当于&a[len(a):]&=&L&。
insert(
&i,&x)
&
在指定位置插入一个元素。第一个参数是准备插入到其前面的那个元素的索引,例如&a.insert(0,&x)&会插入到整个链表之前,而&a.insert(len(a),&x)&相当于&a.append(x)。
remove(
&x)
&
删除链表中值为x的第一个元素。如果没有这样的元素,就会返回一个错误。
pop(
&)
&
从链表的指定位置删除元素,并将其返回。如果没有指定索引,a.pop()&返回最后一个元素。元素随即从链表中被删除。(方法中i两边的方括号表示这个参数是可选的,而不是要求你输入一对方括号,你会经常在Python&库参考手册中遇到这样的标记。)
index(
&x)
&
返回链表中第一个值为x的元素的索引。如果没有匹配的元素就会返回一个错误。
count(
&x)
&
返回x在链表中出现的次数。
sort(
&)
&
对链表中的元素进行适当的排序。
reverse(
&)
&
倒排链表中的元素。
下面这个示例演示了链表的大部分方法:
&;&;&;&a&=&[66.6,&333,&333,&1,&1234.5]
&;&;&;&print&a.count(333),&a.count(66.6),&a.count('x')
2&1&0
&;&;&;&a.insert(2,&-1)
&;&;&;&a.append(333)
&;&;&;&a
[66.6,&333,&-1,&333,&1,&3]
&;&;&;&a.index(333)
1
&;&;&;&a.remove(333)
&;&;&;&a
[66.6,&-1,&333,&1,&3]
&;&;&;&a.reverse()
&;&;&;&a
[333,&,&333,&-1,&66.6]
&;&;&;&a.sort()
&;&;&;&a
[-1,&1,&66.6,&333,&333,&1234.5]
&&
5.1.1&把链表当作堆栈使用&
链表方法使得链表可以很方便的做为一个堆栈来使用,堆栈是这样的数据结构,最先进入的元素最后一个被释放(后进先出)。用&append()&方法可以把一个元素添加到堆栈顶。用不指定索引的&pop()&方法可以把一个元素从堆栈顶释放出来。例如:&
&;&;&;&stack&=&[3,&4,&5]
&;&;&;&stack.append(6)
&;&;&;&stack.append(7)
&;&;&;&stack
[3,&4,&5,&6,&7]
&;&;&;&stack.pop()
7
&;&;&;&stack
[3,&4,&5,&6]
&;&;&;&stack.pop()
6
&;&;&;&stack.pop()
5
&;&;&;&stack
[3,&4]
&&
5.1.2&把链表当作队列使用&
你也可以把链表当做队列使用,队列是这样的数据结构,最先进入的元素最先释放(先进先出)。使用&append()方法可以把元素添加到队列最后,以0为参数调用&pop()&方法可以把最先进入的元素释放出来。例如:
&;&;&;&queue&=&["Eric",&"John",&"Michael"]
&;&;&;&queue.append("Terry")&&&&&&&&&&&#&Terry&arrives
&;&;&;&queue.append("Graham")&&&&&&&&&&#&Graham&arrives
&;&;&;&queue.pop(0)
'Eric'
&;&;&;&queue.pop(0)
'John'
&;&;&;&queue
['Michael',&'Terry',&'Graham']
&&
5.1.3&函数化编程工具&
对于链表来讲,有三个内置函数非常有用:filter(),&map(),&和&reduce()。&
“filter(function,&sequence)”&返回一个序列(sequence),包括了给定序列中所有调用function(item)后返回值为true的元素。(如果可能的话,会返回相同的类型)。例如,以下程序可以计算部分素数:
&;&;&;&def&f(x):&return&x&%&2&!=&0&and&x&%&3&!=&0
...
&;&;&;&filter(f,&range(2,&25))
[5,&7,&11,&13,&17,&19,&23]
“map(function,&sequence)”&为每一个元素依次调用&function(item)&并将返回值组成一个链表返回。例如,以下程序计算立方:
&;&;&;&def&cube(x):&return&x*x*x
...
&;&;&;&map(cube,&range(1,&11))
[1,&8,&27,&64,&125,&216,&343,&512,&729,&1000]
可以传入多个序列,函数也必须要有对应数量的参数,执行时会依次用各序列上对应的元素来调用函数(如果某些序列比其它的短,就用None来代替)。如果把None做为一个函数传入,则直接返回参数做为替代。
组合这两种情况,我们会发现“map(None,&list1,&list2)”是把一对序列变成元素对序列的便捷方式。例如:
&;&;&;&seq&=&range(8)
&;&;&;&def&square(x):&return&x*x
...
&;&;&;&map(None,&seq,&map(square,&seq))
[(0,&0),&(1,&1),&(2,&4),&(3,&9),&(4,&16),&(5,&25),&(6,&36),&(7,&49)]
"reduce(func,&sequence)"&返回一个单值,它是这样构造的:首先以序列的前两个元素调用函数,再以返回值和第三个参数调用,依次执行下去。例如,以下程序计算1到10的整数之和:
&;&;&;&def&add(x,y):&return&x+y
...
&;&;&;&reduce(add,&range(1,&11))
55
如果序列中只有一个元素,就返回它,如果序列是空的,就抛出一个异常。
可以传入第三个参数做为初始值。如果序列是空的,就返回初始值,否则函数会先接收初始值和序列的第一个元素,然后是返回值和下一个元素,依此类推。例如:
&;&;&;&def&sum(seq):
...&&&&&def&add(x,y):&return&x+y
...&&&&&return&reduce(add,&seq,&0)
...&
&;&;&;&sum(range(1,&11))
55
&;&;&;&sum([])
0
不要像示例中这样定义&sum():因为合计数值是一个通用的需求,在新的2.3版中,提供了内置的&sum(sequence)&函数。
5.1.4&链表推导式&
链表推导式提供了一个创建链表的简单途径,无需使用&map(),&filter()&以及&lambda。返回链表的定义通常要比创建这些链表更清晰。每一个链表推导式包括在一个for语句之后的表达式,零或多个for或if语句。返回值是由for或if子句之后的表达式得到的元素组成的链表。如果想要得到一个元组,必须要加上括号。
&;&;&;&freshfruit&=&['&&banana',&'&&loganberry&',&'passion&fruit&&']
&;&;&;&[weapon.strip()&for&weapon&in&freshfruit]
['banana',&'loganberry',&'passion&fruit']
&;&;&;&vec&=&[2,&4,&6]
&;&;&;&[3*x&for&x&in&vec]
[6,&12,&18]
&;&;&;&[3*x&for&x&in&vec&if&x&&;&3]
[12,&18]
&;&;&;&[3*x&for&x&in&vec&if&x&&&2]
[]
&;&;&;&[[x,x**2]&for&x&in&vec]
[[2,&4],&[4,&16],&[6,&36]]
&;&;&;&[x,&x**2&for&x&in&vec]&&&&&&#&error&-&parens&required&for&tuples
&&File&"&stdin&;",&line&1,&in&?
&&&&[x,&x**2&for&x&in&vec]
&&&&&&&&&&&&&&&^
SyntaxError:&invalid&syntax
&;&;&;&[(x,&x**2)&for&x&in&vec]
[(2,&4),&(4,&16),&(6,&36)]
&;&;&;&vec1&=&[2,&4,&6]
&;&;&;&vec2&=&[4,&3,&-9]
&;&;&;&[x*y&for&x&in&vec1&for&y&in&vec2]
[8,&6,&-18,&16,&12,&-36,&24,&18,&-54]
&;&;&;&[x+y&for&x&in&vec1&for&y&in&vec2]
[6,&5,&-7,&8,&7,&-5,&10,&9,&-3]
&;&;&;&[vec1*vec2&for&i&in&range(len(vec1))]
[8,&12,&-54]
为使链表推导式匹配for循环的行为,可以在推导之外保留循环变量:
&;&;&;&x&=&100&&&&&&&&&&&&&&&&&&&&&#&this&gets&overwritten
&;&;&;&[x**3&for&x&in&range(5)]
[0,&1,&8,&27,&64]
&;&;&;&x&&&&&&&&&&&&&&&&&&&&&&&&&&&#&the&final&value&for&range(5)
4
&&
5.2&del&语句
有一个方法可从链表中删除指定索引的元素:del语句。这个方法也可以从链表中删除切片(之前我们是把一个空链表赋给切片)。例如:
&;&;&;&a&=&[-1,&1,&66.6,&333,&333,&1234.5]
&;&;&;&del&a[0]
&;&;&;&a
[1,&66.6,&333,&333,&1234.5]
&;&;&;&del&a[2]
&;&;&;&a
[1,&66.6,&1234.5]
del&也可以用于删除整个变量:
&;&;&;&del&a
此后再引用这个名字会发生错误(至少要到给它赋另一个值为止)。后面我们还会发现del的其它用法。
&&
5.3&元组(Tuples)和序列(Sequences&)
我们知道链表和字符串有很多通用的属性,例如索引和切片操作。它们是序列类型中的两种。因为Python是一个在不停进化的语言,也可以加入其它的序列类型,这里有另一种标准序列类型:元组。
一个元组由数个逗号分隔的值组成,例如:
&;&;&;&t&=&1,&'hello!'
&;&;&;&t[0]
12345
&;&;&;&t
(1,&'hello!')
&;&;&;&#&Tuples&may&be&nested:
...&u&=&t,&(1,&2,&3,&4,&5)
&;&;&;&u
((1,&'hello!'),&(1,&2,&3,&4,&5))
如你所见,元组在输出时总是有括号的,以便于正确表达嵌套结构。在输入时可能有或没有括号都可以,不过经常括号都是必须的(如果元组是一个更大的表达式的一部分)。
元组有很多用途。例如(x,&y)坐标点,数据库中的员工记录等等。元组就像字符串,不可改变:不能给元组的一个独立的元素赋值(尽管你可以通过联接和切片来模仿)。也可以通过包含可变对象来创建元组,例如链表。
一个特殊的问题是构造包含零个或一个元素的元组:为了适应这种情况,语法上有一些额外的改变。一对空的括号可以创建空元组;要创建一个单元素元组可以在值后面跟一个逗号(在括号中放入一个单值是不够的)。丑陋,但是有效。例如:
&;&;&;&empty&=&()
&;&;&;&singleton&=&'hello',&&&&#&&--&note&trailing&comma
&;&;&;&len(empty)
0
&;&;&;&len(singleton)
1
&;&;&;&singleton
('hello',)
语句&t&=&1,&'hello!'&是元组封装(sequence&packing)的一个例子:值&12345,&54321&和&'hello!'&被封装进元组。其逆操作可能是这样:
&;&;&;&x,&y,&z&=&t
这个调用被称为序列拆封非常合适。序列拆封要求左侧的变量数目与序列的元素个数相同。要注意的是可变参数(multiple&assignment&
)其实只是元组封装和序列拆封的一个结合!
这里有一点不对称:封装多重参数通常会创建一个元组,而拆封操作可以作用于任何序列。
&&
5.4&字典(Dictionaries)&
另一个非常有用的Python内建数据类型是字典(Dictionaries)。字典在某些语言中可能称为“联合内存”(``associative&memories'')或“联合数组”(``associative&arrays'')。序列是以连续的整数为索引,与此不同的是,字典以关键字为索引,关键字可以是任意不可变类型,通常用字符串或数值。如果元组中只包含字符串和数字,它可以做为关键字,如果它直接或间接的包含了可变对象,就不能当做关键字。不能用链表做关键字,因为链表可以用它们的&append()&和&extend()&方法,或者用切片、或者通过检索变量来即时改变。
理解字典的最佳方式是把它看做无序的关键字:值对(&key:value&pairs&)集合,关键字必须是互不相同的(在同一个字典之内)。一对大括号创建一个空的字典:{}。初始化链表时,在大括号内放置一组逗号分隔的关键字:值对,这也是字典输出的方式。
字典的主要操作是依据关键字来存储和析取值。也可以用del来删除关键字:值对。如果你用一个已经存在的关键字存储值,以前为该关键字分配的值就会被遗忘。试图析取从一个不存在的关键字中读取值会导致错误。
字典的keys()&方法返回由所有关键字组成的链表,该链表的顺序不定(如果你需要它有序,只能调用关键字链表的sort()方法)。使用字典的&has_key()&方法可以检查字典中是否存在某一关键字。
这是一个关于字典应用的小示例:
&;&;&;&tel&=&{'jack':&4098,&'sape':&4139}
&;&;&;&tel['guido']&=&4127
&;&;&;&tel
{'sape':&4139,&'guido':&4127,&'jack':&4098}
&;&;&;&tel['jack']
4098
&;&;&;&del&tel['sape']
&;&;&;&tel['irv']&=&4127
&;&;&;&tel
{'guido':&4127,&'irv':&4127,&'jack':&4098}
&;&;&;&tel.keys()
['guido',&'irv',&'jack']
&;&;&;&tel.has_key('guido')
True
链表中存储关键字-值对元组的话,字典可以从中直接构造。关键字-值对来自一个模式时,可以用链表推导式简单的表达关键字-值链表。
&;&;&;&dict([('sape',&4139),&('guido',&4127),&('jack',&4098)])
{'sape':&4139,&'jack':&4098,&'guido':&4127}
&;&;&;&dict([(x,&x**2)&for&x&in&vec])&&&&&#&use&a&list&comprehension
{2:&4,&4:&16,&6:&36}
&&
5.5&循环技巧&
在字典中循环时,关键字和对应的值可以使用&items()&方法同时解读出来。
&;&;&;&knights&=&{'gallahad':&'the&pure',&'robin':&'the&brave'}
&;&;&;&for&k,&v&in&knights.items():
...&&&&&print&k,&v
...
gallahad&the&pure
robin&the&brave
在序列中循环时,索引位置和对应值可以使用&enumerate()&函数同时得到。&
&
&;&;&;&for&i,&v&in&enumerate(['tic',&'tac',&'toe']):
...&&&&&print&i,&v
...
0&tic
1&tac
2&toe
同时循环两个或更多的序列,可以使用&zip()&整体解读。&
&;&;&;&questions&=&['name',&'quest',&'favorite&color']
&;&;&;&answers&=&['lancelot',&'the&holy&grail',&'blue']
&;&;&;&for&q,&a&in&zip(questions,&answers):
...&&&&&print&'What&is&your&%s?&&It&is&%s.'&%&(q,&a)
...&&&&&
What&is&your&name?&&It&is&lancelot.
What&is&your&quest?&&It&is&the&holy&grail.
What&is&your&favorite&color?&&It&is&blue.
&&
5.6&深入条件控制&
用于while和if语句的条件包括了比较之外的操作符。
in和not比较操作符审核值是否在一个区间之内。操作符is和is&not比较两个对象是否相同;这只和诸如链表这样的可变对象有关。所有的比较操作符具有相同的优先级,低于所有的数值操作。
比较操作可以传递。例如&a&&&b&==&c&审核是否a小于b并b等于c。
比较操作可以通过逻辑操作符and和or组合,比较的结果可以用not来取反义。这些操作符的优先级又低于比较操作符,在它们之中,not具有最高的优先级,or的优先组最低,所以A&and&not&B&or&C&等于&(A&and&(not&B))&or&C。当然,表达式可以用期望的方式表示。
逻辑操作符and&和or&也称作短路操作符:它们的参数从左向右解析,一旦结果可以确定就停止。例如,如果A和C为真而B为假,A&and&B&and&C&不会解析C。作用于一个普通的非逻辑值时,短路操作符的返回值通常是最后一个变量。
可以把比较或其它逻辑表达式的返回值赋给一个变量,例如:
&;&;&;&string1,&string2,&string3&=&'',&'Trondheim',&'Hammer&Dance'
&;&;&;&non_null&=&string1&or&string2&or&string3
&;&;&;&non_null
'Trondheim'
需要注意的是Python与C不同,内部表达式不能分配值。C&程序员经常对此抱怨,不过它避免了一类在C程序中司空见惯的错误:想要在解析式中使==时误用了=操作符。&
&&
5.7&比较序列和其它类型
序列对象可以与相同类型的其它对象比较。比较操作按字典序进行:首先比较前两个元素,如果不同,就决定了比较的结果;如果相同,就比较后两个元素,依此类推,直到所有序列都完成比较。如果两个元素本身就是同样类型的序列,就递归字典序比较。如果两个序列的所有子项都相等,就认为序列相等。如果一个序列是另一个序列的初始子序列,较短的一个序列就小于另一个。字符串的字典序按照单字符的ASCII顺序。下面是同类型序列之间比较的一些例子:
(1,&2,&3)&&&&&&&&&&&&&&&&(1,&2,&4)
[1,&2,&3]&&&&&&&&&&&&&&&&[1,&2,&4]
'ABC'&&&'C'&&&'Pascal'&&&'Python'
(1,&2,&3,&4)&&&&&&&&&&&&&(1,&2,&4)
(1,&2)&&&&&&&&&&&&&&&&&&&(1,&2,&-1)
(1,&2,&3)&&&&&&&&&&&&&==&(1.0,&2.0,&3.0)
(1,&2,&('aa',&'ab'))&&&&&(1,&2,&('abc',&'a'),&4)
需要注意的是不同类型的对象比较是合法的。输出结果是确定而非任意的:类型按它们的名字排序。因而,一个链表(list)总是小于一个字符串(string),一个字符串(string)总是小于一个元组(tuple)等等。数值类型比较时会统一它们的数据类型,所以0等于0.0,等等。5.1
& 回复于: 16:55:54
6.&模块
如果你退出Python解释器重新进入,以前创建的一切定义(变量和函数)就全部丢失了。因此,如果你想写一些长久保存的程序,最好使用一个文本编辑器来编写程序,把保存好的文件输入解释器。我们称之为创建一个脚本。程序变得更长一些了,你可能为了方便维护而把它分离成几个文件。你也可能想要在几个程序中都使用一个常用的函数,但是不想把它的定义复制到每一个程序里。
为了支持这些需要,Python提供了一个方法可以从文件中获取定义,在脚本或者解释器的一个交互式实例中使用。这样的文件被称为实例;模块中的定义可以导入到另一个模块或主模块中(在脚本执行时可以调用的变量集位于最高级,并且处于计算器模式)
模块是包括Python定义和声明的文件。文件名就是模块名加上.py后缀。模块的模块名(做为一个字符串)可以由全局变量__name__得到。例如,你可以用自己惯用的文件编辑器在当前目录下创建一个叫fibo.py的文件,录入如下内容:
#&Fibonacci&numbers&module
def&fib(n):&&&&#&write&Fibonacci&series&up&to&n
&&&&a,&b&=&0,&1
&&&&while&b&&&n:
&&&&&&&&print&b,
&&&&&&&&a,&b&=&b,&a+b
def&fib2(n):&#&return&Fibonacci&series&up&to&n
&&&&result&=&[]
&&&&a,&b&=&0,&1
&&&&while&b&&&n:
&&&&&&&&result.append(b)
&&&&&&&&a,&b&=&b,&a+b
&&&&return&result
现在进入Python解释器用如下命令导入这个模块:
&;&;&;&import&fibo
这样做不会直接把fibo中的函数导入当前的语义表;,它只是引入了模块名fibo。你可以通过模块名按如下方式访问这个函数:
&;&;&;&fibo.fib(1000)
1&1&2&3&5&8&13&21&34&55&89&144&233&377&610&987
&;&;&;&fibo.fib2(100)
[1,&1,&2,&3,&5,&8,&13,&21,&34,&55,&89]
&;&;&;&fibo.__name__
'fibo'
如果你想要直接调用函数,通常可以给它赋一个本地名称:
&;&;&;&fib&=&fibo.fib
&;&;&;&fib(500)
1&1&2&3&5&8&13&21&34&55&89&144&233&377
&&
6.1&深入模块
模块可以像函数定义一样包含执行语句。这些语句通常用于初始化模块。它们只在模块第一次导入时执行一次。6.1&
对应于定义模块中所有函数的全局语义表,每一个模块有自己的私有语义表。因此,模块作者可以在模块中使用一些全局变量,不会因为与用户的全局变量冲突而引发错误。另一方面,如果你确定你需要这个,可以像引用模块中的函数一样获取模块中的全局变量,形如:modname.itemname。
模块可以导入(import)其它模块。习惯上所有的import语句都放在模块(或脚本,等等)的开头,但这并不是必须的。被导入的模块名入在本模块的全局语义表中。
import语句的一个变体直接从被导入的模块中导入命名到本模块的语义表中。例如:
&;&;&;&from&fibo&import&fib,&fib2
&;&;&;&fib(500)
1&1&2&3&5&8&13&21&34&55&89&144&233&377
这样不会从局域语义表中导入模块名(例如,fibo没有定义)。
这里还有一个变体从模块定义中导入所有命名:
&;&;&;&from&fibo&import&*
&;&;&;&fib(500)
1&1&2&3&5&8&13&21&34&55&89&144&233&377
这样可以导入所有除了以下划线(_)开头的命名。
&&
6.1.1&模块搜索路径
&导入一个叫spam的模块时,解释器先在当前目录中搜索名为spam.py的文件,然后在环境变量PYTHONPATH指琮的目录列表中搜索,然后是环境变量PATH中的路径列表。如果PYTHONPATH没有设置,或者文件没有找到,接下来搜索安装目录,在UNIX中,通常是&.:/usr/local/lib/python。
实际上,解释器由sys.path变量指定的路径目录搜索模块,该变量初始化时默认包含了输入脚本(或者当前目录),PATHPATH和安装目录。这样就允许Python程序(原文如此,programs;我猜想应该是“programer”,程序员--译者)了解如何修改或替换模块搜索目录。需要注意的是由于这些目录中包含有搜索路径中运行的脚本,所以这些脚本不应该和标准模块重名,否则在导入模块时Python会尝试把这些脚本当作模块来加载。这通常会引发一个错误。请参见&6.2节“标准模块”以了解更多的信息。
6.1.2&“编译”Python文件
对于引用了大量标准模块的短程序,有一个提高启动速度有重要方法,如果在spam.py目录下存在一个名为spam.pyc的文件,它会被视为spam模块的预“编译”(``byte-compiled''&,二进制编译)版本。用于创建spam.pyc的这一版spam.py的修改时间记录在spam.pyc文件中,如果两者不匹配,.pyc文件就被忽略。
通常你不需要为创建spam.pyc文件做任何工作。一旦spam.py成功编译,就会试图编译对应版本的spam.pyc。如果有任何原因导致写入不成功,返回的spam.pyc文件就会视为无效,随后即被忽略。spam.pyc文件的内容是平台独立的,所以Python模块目录可以在不同架构的机器之间共享。
部分高级技巧:
以-O参数调用Python解释器时,会生成优化代码并保存在.pyo文件中。通用的优化器没有太多帮助;它只是删除了断言(assert)语句。使用-O参数,所有的代码都会被优化;.pyc文件被忽略,.py文件被编译为优化代码。
向Python解释器传递两个&-O&参数(-OO)会执行完全优化的二进制优化编译,这偶尔会生成错误的程序。当前,压缩的.pyo文件只是从二进制代码中删除了__doc__字符串。因为某些程序依赖于这些变量的可用性,你应该只在确定无误的场合使用这一选项。
来自.pyc文件或.pyo文件中的程序不会比来自.py文件的运行更快;.pyc或.pyo文件只是在它们加载的时候更快一些。
通过脚本名在命令行运行脚本时,不会为该脚本向创建.pyc或.pyo文件的二进制代码。当然,把脚本的主要代码移进一个模块里,然后用一个小的解构脚本导入这个模块,就可以提高脚本的启动速度。也可以直接在命令行中指定一个.pyc或乾.pyo文件。
对于同一个模块(这里指例程spam--译者),可以只有spam.pyc文件(或者spam.pyo,在使用&-O&参数时)而没有spam.py文件。这样可以打包发布比较于逆向工程的Python代码库。
compileall模块&可以为指定目录中的所有模块创建.pyc文件(或者使用-O参数创建.pyo文件)。
&&
6.2&标准模块
Python带有一个标准模块库,并发布有独立的文档,名为&Python&库参考手册&(此后称其为“库参考手册”)。有一些模块内置于解释器之中,这些操作的访问接口不是语言内核的一部分,但是已经内置于解释器了。这既是为了提高效率,也是为了给系统调用等操作系统原生访问提供接口。这类模块集合是一个依赖于底层平台的配置选项。例如,amoeba模块只提供对Amoeba原生系统的支持。有一个具体的模块值得注意:sys&,这个模块内置于所有的Python解释器。变量&sys.ps1&和&sys.ps2&定义了主提示符和副助提示符字符串:
&;&;&;&import&sys
&;&;&;&sys.ps1
'&;&;&;&'
&;&;&;&sys.ps2
'...&'
&;&;&;&sys.ps1&=&'C&;&'
C&;&print&'Yuck!'
Yuck!
C&;
这两个变量只在解释器的交互模式下有意义(此处原文为:These&two&variables&are&only&defined&if&the&interpreter&is&in&interactive&mode.&)。
变量sys.path&是解释器模块搜索路径的字符串列表。它由环境变量PYTHONPATH初始化,如果PYTHONPATH没有内定,就由内置的默认值初始化。你可以用标准和字符串操作修改它:
&;&;&;&import&sys
&;&;&;&sys.path.append('/ufs/guido/lib/python')
&&
6.3&dir()&函数
内置函数dir()用于按模块名搜索模块定义,它返回一个字符串类型的存储列表:
&;&;&;&import&fibo,&sys
&;&;&;&dir(fibo)
['__name__',&'fib',&'fib2']
&;&;&;&dir(sys)
['__displayhook__',&'__doc__',&'__excepthook__',&'__name__',&'__stderr__',
&'__stdin__',&'__stdout__',&'_getframe',&'api_version',&'argv',&
&'builtin_module_names',&'byteorder',&'callstats',&'copyright',
&'displayhook',&'exc_clear',&'exc_info',&'exc_type',&'excepthook',
&'exec_prefix',&'executable',&'exit',&'getdefaultencoding',&'getdlopenflags',
&'getrecursionlimit',&'getrefcount',&'hexversion',&'maxint',&'maxunicode',
&'meta_path',&'modules',&'path',&'path_hooks',&'path_importer_cache',
&'platform',&'prefix',&'ps1',&'ps2',&'setcheckinterval',&'setdlopenflags',
&'setprofile',&'setrecursionlimit',&'settrace',&'stderr',&'stdin',&'stdout',
&'version',&'version_info',&'warnoptions']
无参数调用时,dir()函数返回你当前定义的名称:
&;&;&;&a&=&[1,&2,&3,&4,&5]
&;&;&;&import&fibo,&sys
&;&;&;&fib&=&fibo.fib
&;&;&;&dir()
['__name__',&'a',&'fib',&'fibo',&'sys']
应该该列表列出了所有类型的名称:变量,模块,函数,等等:
dir()不会列出内置函数和变量名。如果你想列出这此内容,它们在标准模块__buildin__中定义:
&;&;&;&import&__builtin__
&;&;&;&dir(__builtin__)
['ArithmeticError',&'AssertionError',&'AttributeError',
&'DeprecationWarning',&'EOFError',&'Ellipsis',&'EnvironmentError',
&'Exception',&'False',&'FloatingPointError',&'IOError',&'ImportError',
&'IndentationError',&'IndexError',&'KeyError',&'KeyboardInterrupt',
&'LookupError',&'MemoryError',&'NameError',&'None',&'NotImplemented',
&'NotImplementedError',&'OSError',&'OverflowError',&'OverflowWarning',
&'PendingDeprecationWarning',&'ReferenceError',
&'RuntimeError',&'RuntimeWarning',&'StandardError',&'StopIteration',
&'SyntaxError',&'SyntaxWarning',&'SystemError',&'SystemExit',&'TabError',
&'True',&'TypeError',&'UnboundLocalError',&'UnicodeError',&'UserWarning',
&'ValueError',&'Warning',&'ZeroDivisionError',&'__debug__',&'__doc__',
&'__import__',&'__name__',&'abs',&'apply',&'bool',&'buffer',
&'callable',&'chr',&'classmethod',&'cmp',&'coerce',&'compile',&'complex',
&'copyright',&'credits',&'delattr',&'dict',&'dir',&'divmod',
&'enumerate',&'eval',&'execfile',&'exit',&'file',&'filter',&'float',
&'getattr',&'globals',&'hasattr',&'hash',&'help',&'hex',&'id',
&'input',&'int',&'intern',&'isinstance',&'issubclass',&'iter',
&'len',&'license',&'list',&'locals',&'long',&'map',&'max',&'min',
&'object',&'oct',&'open',&'ord',&'pow',&'property',&'quit',
&'range',&'raw_input',&'reduce',&'reload',&'repr',&'round',
&'setattr',&'slice',&'staticmethod',&'str',&'string',&'sum',&'super',
&'tuple',&'type',&'unichr',&'unicode',&'vars',&'xrange',&'zip']
&&
6.4&包
包通常是使用用“圆点模块名”的结构化模块命名空间。例如,名为A.B的模块表示了名为“A”的包中名为“B”的子模块。正如同用模块来保存不同的模块架构可以避免全局变量之间的相互冲突,使用圆点模块名保存像NunPy或Python&Imaging&Library之类的不同类库架构可以避免模块之间的命名冲突。
假设你现在想要设计一个模块集(一个“包”)来统一处理声音文件和声音数据。存在几种不同的声音格式(通常由它们的扩展名来标识,例如:.wav,.aiff,.au),于是,为了在不同类型的文件格式之间转换,你需要维护一个不断增长的包集合。可能你还想要对声音数据做很多不同的操作(例如混音,添加回声,应用平衡功能,创建一个人造效果),所以你要加入一个无限流模块来执行这些操作。你的包可能会是这个样子(通过分级的文件体系来进行分组):
Sound/&&&&&&&&&&&&&&&&&&&&&&&&&&Top-level&package
&&&&&&__init__.py&&&&&&&&&&&&&&&Initialize&the&sound&package
&&&&&&Formats/&&&&&&&&&&&&&&&&&&Subpackage&for&file&format&conversions
&&&&&&&&&&&&&&__init__.py
&&&&&&&&&&&&&&wavread.py
&&&&&&&&&&&&&&wavwrite.py
&&&&&&&&&&&&&&aiffread.py
&&&&&&&&&&&&&&aiffwrite.py
&&&&&&&&&&&&&&auread.py
&&&&&&&&&&&&&&auwrite.py
&&&&&&&&&&&&&&...
&&&&&&Effects/&&&&&&&&&&&&&&&&&&Subpackage&for&sound&effects
&&&&&&&&&&&&&&__init__.py
&&&&&&&&&&&&&&echo.py
&&&&&&&&&&&&&&surround.py
&&&&&&&&&&&&&&reverse.py
&&&&&&&&&&&&&&...
&&&&&&Filters/&&&&&&&&&&&&&&&&&&Subpackage&for&filters
&&&&&&&&&&&&&&__init__.py
&&&&&&&&&&&&&&equalizer.py
&&&&&&&&&&&&&&vocoder.py
&&&&&&&&&&&&&&karaoke.py
&&&&&&&&&&&&&&...
导入模块时,Python通过sys.path中的目录列表来搜索存放包的子目录。
必须要有一个__init__.py&文件的存在,才能使Python视该目录为一个包;这是为了防止某些目录使用了“string”这样的通用名而无意中在随后的模块搜索路径中覆盖了正确的模块。最简单的情况下,__init__.py&可以只是一个空文件,不过它也可能包含了包的初始化代码,或者设置了&__all__&变量,后面会有相关介绍。
包用户可以从包中导入合法的模块,例如:
import&Sound.Effects.echo
这样就导入了Sound.Effects.echo子模块。它必需通过完整的名称来引用。
Sound.Effects.echo.echofilter(input,&output,&delay=0.7,&atten=4)
导入包时有一个可以选择的方式:
from&Sound.Effects&import&echo
这样就加载了echo子模块,并且使得它在没有包前缀的情况下也可以使用,所以它可以如下方式调用:
echo.echofilter(input,&output,&delay=0.7,&atten=4)
还有另一种变体用于直接导入函数或变量:
from&Sound.Effects.echo&import&echofilter
这样就又一次加载了echo子模块,但这样就可以直接调用它的&echofilter()&函数:
echofilter(input,&output,&delay=0.7,&atten=4)
需要注意的是使用&from&package&import&item&方式导入包时,这个子项(item)既可以是包中的一个子模块(或一个子包),也可以是包中定义的其它命名,像函数、类或变量。import&语句首先核对是否包中有这个子项,如果没有,它假定这是一个模块,并尝试加载它。如果没有找到它,会引发一个&ImportError&异常。
相反,使用类似import&item.subitem.subsubitem&这样的语法时,这些子项必须是包,最后的子项可以是包或模块,但不能是前面子项中定义的类、函数或变量。
&&
6.4.1&从包中导入全部信息(Importing&*&From&a&Package)&
那么当用户写下from&Sound.Effects&import&*时会发生什么事?理想中,总是希望在文件系统中找出包中所有的子模块,然后导入它们。不幸的是,这个操作在Mac&和&Windows&平台上工作的并不太好,这些文件系统的文件大小写并不敏感!在这些平台上没有什么方法可以确保一个叫ECHO.PY的文件应该导入为模块echo、Echo或ECHO。(例如,Windows&95有一个讨厌的习惯,它会把所有的文件名都显示为首字母大写的风格。)&DOS&8+3文件名限制又给长文件名模块带来了另一个有趣的问题。
对于包的作者来说唯一的解决方案就是给提供一个明确的包索引。import语句按如下条件进行转换:执行from&packae&import&*&时,如果包中的__init__.py代码定义了一个名为__all__的链表,就会按照链表中给出的模块名进行导入。新版本的包发布时作者可以任意更新这个链表。如果包作者不想import&*&的时候导入他们的包中所有模块,那么也可能会决定不支持它(import&*)。例如,Sounds/Effects/__init__.py&这个文件可能包括如下代码:
__all__&=&["echo",&"surround",&"reverse"]
这意味着&from&Sound.Effects&import&*&语句会从Sound&包中导入以上三个已命名的子模块。
如果没有定义&__all__&,from&Sound.Effects&import&*&语句不会从Sound.Effects包中导入所有的子模块。Effects&导入到当前的命名空间,只能确定的是导入了&Sound.Effects&包(可能会运行&__init__.py中的初始化代码)以及包中定义的所有命名会随之导入。这样就从__init__.py中导入了每一个命名(以及明确导入的子模块)。同样也包括了前述的import语句从包中明确导入的子模块,考虑以下代码:
import&Sound.Effects.echo
import&Sound.Effects.surround
from&Sound.Effects&import&*
在这个例子中,echo和surround模块导入了当前的命名空间,这是因为执行from&...&import语句时它们已经定义在Sound.Effects包中了(定义了__all__时也会同样工作)。
需要注意的是习惯上不主张从一个包或模块中用import&*&导入所有模块,因为这样的通常意味着可读性会很差。然而,在交互会话中这样做可以减少输入,相对来说确定的模块被设计成只导出确定的模式中命名的那一部分。
记住,from&Package&import&specific_submodule没有错误!事实上,除非导入的模块需要使用其它包中的同名子模块,否则这是受到推荐的写法。
6.4.2&内置包(Intra-package)参考
子模块之间经常需要互相引用。例如,surround&模块可能会引用echo&模块。事实上,这样的引用如此普遍,以致于import语句会先搜索包内部,然后才是标准模块搜索路径。因此surround&module&可以简单的调用import&echo&或者&from&echo&import&echofilter。如果没有在当前的包中发现要导入的模块,import语句会依据指定名寻找一个顶级模块。
如果包中使用了子包结构(就像示例中的Sound包),不存在什么从邻近的包中引用子模块的便捷方法--必须使用子包的全名。例如,如果Sound.Filters.vocoder&包需要使用Sound.Effects&包中的echosa模块,它可以使用from&Sound.Effects&import&echo。
6.4.3&多重路径中的包
包支持一个另为特殊的变量,&__path__。&在包的__init__.py文件代码执行之前,该变量初始化一个目录名列表。该变量可以修改,它作用于包中的子包和模块的搜索功能。
这个功能可以用于扩展包中的模块集,不过它不常用。
& 回复于: 16:56:30
7.&输入和输出
有几种方法可以表现程序的输出结果;数据可以用可读的结构打印,也可以写入文件供以后使用。本章将会讨论几种可行的做法。
&&
7.1&设计输出格式&
我们有两种大相径庭的输出值方法:表达式语句和print语句。(第三种访求是使用文件对象的wite()方法,标准文件输出可以参考sys.stdout。详细内容参见库参考手册。)
可能你经常想要对输出格式做一些比简单的打印空格分隔符更为复杂的控制。有两种方法可以格式化输出。第一种是由你来控制整个字符串,使用字符切片和联接操作就可以创建出任何你想要的输出形式。标准模块&string&包括了一些操作,将字符串填充入给定列时,这些操作很有用。随后我们会讨论这部分内容。第二种方法是使用&%&操作符,以某个字符串做为其左参数。&%&操作符将左参数解释为类似于&sprintf()风格的格式字符串,并作用于右参数,从该操作中返回格式化的字符串。
当然,还有一个问题,如何将(不同的)值转化为字符串?很幸运,Python总是把任意值传入&repr()&或&str()&函数,转为字符串。相对而言引号('')等价于repr(),不过不提倡这样用。
函数str()&用于将值转化为适于人阅读的形式,而&repr()转化为供解释器读取的形式(如果没有等价的语法,则会发生SyntaxError&异常)&某对象没有适于人阅读的解释形式的话,str()会返回与repr()等同的值。很多类型,诸如数值或链表、字典这样的结构,针对各函数都有着统一的解读方式。字符串和浮点数,有着独特的解读方式。
以下是一些示例:
&;&;&;&s&=&'Hello,&world.'
&;&;&;&str(s)
'Hello,&world.'
&;&;&;&repr(s)
"'Hello,&world.'"
&;&;&;&str(0.1)
'0.1'
&;&;&;&repr(0.1)
'0.00001'
&;&;&;&x&=&10&*&3.25
&;&;&;&y&=&200&*&200
&;&;&;&s&=&'The&value&of&x&is&'&+&repr(x)&+&',&and&y&is&'&+&repr(y)&+&'...'
&;&;&;&print&s
The&value&of&x&is&32.5,&and&y&is&40000...
&;&;&;&#&The&repr()&of&a&string&adds&string&quotes&and&backslashes:
...&hello&=&'hello,&world\n'
&;&;&;&hellos&=&repr(hello)
&;&;&;&print&hellos
'hello,&world\n'
&;&;&;&#&The&argument&to&repr()&may&be&any&Python&object:
...&repr((x,&y,&('spam',&'eggs')))
"(32.5,&40000,&('spam',&'eggs'))"
&;&;&;&#&reverse&quotes&are&convenient&in&interactive&sessions:
...&`x,&y,&('spam',&'eggs')`
"(32.5,&40000,&('spam',&'eggs'))"
以下两种方法可以输出平方和立方表:
&;&;&;&import&string
&;&;&;&for&x&in&range(1,&11):
...&&&&&print&string.rjust(repr(x),&2),&string.rjust(repr(x*x),&3),
...&&&&&#&Note&trailing&comma&on&previous&line
...&&&&&print&string.rjust(repr(x*x*x),&4)
...
&1&&&1&&&&1
&2&&&4&&&&8
&3&&&9&&&27
&4&&16&&&64
&5&&25&&125
&6&&36&&216
&7&&49&&343
&8&&64&&512
&9&&81&&729
10&100&1000
&;&;&;&for&x&in&range(1,11):
...&&&&&print&'%2d&%3d&%4d'&%&(x,&x*x,&x*x*x)
...&
&1&&&1&&&&1
&2&&&4&&&&8
&3&&&9&&&27
&4&&16&&&64
&5&&25&&125
&6&&36&&216
&7&&49&&343
&8&&64&&512
&9&&81&&729
10&100&1000
(需要注意的是使用print方法时每两列之间有一个空格:它总是在参数之间加一个空格。)
以上是一个string.rjust()函数的演示,这个函数把字符串输出到一列,并通过向左侧填充空格来使其右对齐。类似的函数还有&string.ljust()&和&string.center()。这些函数只是输出新的字符串,并不改变什么。如果输出的字符串太长,它们也不会截断它,而是原样输出,这会使你的输出格式变得混乱,不过总强过另一种选择(截断字符串),因为那样会产生错误的输出值。(如果你确实需要截断它,可以使用切片操作,例如:"string.ljust(x,&n)[0]"。)
还有一个函数,string.zfill()它用于向数值的字符串表达左侧填充0。该函数可以正确理解正负号:
&;&;&;&import&string
&;&;&;&string.zfill('12',&5)
'00012'
&;&;&;&string.zfill('-3.14',&7)
'-003.14'
&;&;&;&string.zfill('3.',&5)
'3.'
可以如下这样使用&%&操作符:&
&;&;&;&import&math
&;&;&;&print&'The&value&of&PI&is&approximately&%5.3f.'&%&math.pi
The&value&of&PI&is&approximately&3.142.
如果有超过一个的字符串要格式化为一体,就需要将它们传入一个元组做为右值,如下所示:
&;&;&;&table&=&{'Sjoerd':&4127,&'Jack':&4098,&'Dcab':&7678}
&;&;&;&for&name,&phone&in&table.items():
...&&&&&print&'%-10s&==&;&%10d'&%&(name,&phone)
...&
Jack&&&&&&&==&;&&&&&&&4098
Dcab&&&&&&&==&;&&&&&&&7678
Sjoerd&&&&&==&;&&&&&&&4127
大多数类C的格式化操作都需要你传入适当的类型,不过如果你没有定义异常,也不会有什么从内核中主动的弹出来。(however,&if&you&don't&you&get&an&exception,&not&a&core&dump)使用&%s&格式会更轻松些:如果对应的参数不是字符串,它会通过内置的&str()&函数转化为字符串。Python支持用&*&作为一个隔离(整型的)参数来传递宽度或精度。Python不支持C的&%n&和&%p&操作符。
如果可以逐点引用要格式化的变量名,就可以产生符合真实长度的格式化字符串,不会产生间隔。这一效果可以通过使用&form&%(name)结构来实现:
&;&;&;&table&=&{'Sjoerd':&4127,&'Jack':&4098,&'Dcab':&8637678}
&;&;&;&print&'Jack:&%(Jack)d;&Sjoerd:&%(Sjoerd)d;&Dcab:&%(Dcab)}

我要回帖

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信