??xml version="1.0" encoding="utf-8" standalone="yes"?> q是一个再单不q的赋D句,即便是才开始学?fn)编E的新手也能脱口而出它的含义 -- “设|变量i的gؓ(f)1”?/p>
i = 2
“将变量i的值改?”,当看到接下来q行代码Ӟ你脑中肯定?x)立xQ现这L(fng)念头?/p>
q难道会(x)有问题嘛Q这单单的一行赋D句其实包含了(jin)python中的三个重要概念Q名字、绑定和对象?br />python对赋D句作Z(jin)自己的定义:(x) 名字l定到对象这个概念在python中随处可见,可以说是python的最基本而且最重要的概念之一。如?br />没有很好理解q一点,一些意想不到的l果׃(x)在?zhn)的代码中?zhn)然出现?/p>
先来看一个简单例子:(x)
>>> a = {'g':1} Z意料嘛?h慢看完这文章?/p>
1. 对象 在python中,所有对象都有下面三个特征:(x) 一旦对象被创徏Q它的标识码׃允许更改。对象的标识码可以有内徏函数id()获取Q它是一个整型数。?zhn)可以它惌对象在内存中的地址Q其实在目前的实C标识码也是该对象的内存地址?/p>
>>> class c1: 换算一下,11274040是十六q制?x00AC0738?/p>
>>> id(1)
q就是前面提到的1q个对象的标识码Q也是它在内存中的地址?/font>
当用is操作W比较两个对象时Q就是在比较它们的标识码。更切地说Qis操作W是在判断两个对象是否是同一个对象?br />>>> [1] is [1]
>>> [1] == [1]
与对象的标识码类|对象的类型也是不可更改的。可以用内徏函数type()取得对象的类型?/p>
有的对象的值是可以改变的,q类对象叫作可变对象Q而另外一些对象在创徏后其值是不可改变的(?q个对象Q,q类对象叫作恒定对象。对象的可变性是由它的类型决定的Q比如数值型(number)、字W串?string)以及(qing)序列?tuple)的对象是恒定对象Q而字典型(dictionary)和列表型(list)的对象是可变对象?/p>
除了(jin)上面提到的三个特征外Q一个对象可能:(x) 2. 名字 名字在一定的名字I间内有效,而且唯一Q不可能在同一个名字空间内有两个或更多的对象取同一名字?/p>
让我们再来看看本的W一个例子:(x)i = 1。在python中,它有如下两个含义Q?br /> * 创徏一个gؓ(f)1的整型对?br /> * "i"是指向该整型对象的名字(而且它是一个引用)(j)
i=i+1
* q创Z(jin)一个新的对象,其gؓ(f)i+1?br />* "i"q个名字指向?jin)该新徏的对象,该对象的引用计数加一Q?i"以前所指向的老对象的 3.1 引用计数 对象的引用计数在下列情况下会(x)减少Q?br /> * d?jin)当前的名字I间Q该名字I间中的本地名字都会(x)被销毁)(j) 当对象的引用计数降到0后,该对象就?x)被销毁,其所占的内存也就得以回收?/p>
4. 名字l定所带来的一些奇特现?/p>
?.1Q?br />>>> li1 = [7, 8, 9, 10] 注解Q这里li1与li2都指向同一个列表对象[7, 8, 9, 10]Q“li[1] = 16”是改变该列表中的第2个元素,所以通过li2时同样会(x)看到q一改动?/p>
?.2Q?br />>>> b = [{'g':1}]*4
?.3Q?br />
>>> b = [{'g':1}] + [{'g':1}] + [{'g':1}] + [{'g':1}]
注解Q在有的python书中讲到乘法W号Q?Q就相当于几个加法的重复Q即认ؓ(f)?.2应该?.3的结果一致?br /> 其实不然。例4.2中的bq个列表中的每一个元素{'g': 1}其实都是同一个对象,可以用id(b[n])q行验证。而例4.3中则是四个不同的对象。我们可以采用名字绑定的Ҏ(gu)消除q一歧义Q?/font>
>>> a = {'g' : 1}
>>> a = {'g' : 1} 不过对于恒定对象而言Q?”和q箋加法的效果一栗比如,b=[1] * 4 q同于 b=[1]+[1]+[1]+[1]?/p>
5. 函数的传参问?br /> 函数的参C递也是一个名字与对象的绑定过E,而且是绑定到另外一个名字空_(d)卛_C内部的名字空_(d)(j)。python对赋D句的独特看法又会(x)对函数的传递造成什么媄(jing)响呢Q?/p>
5.1 传|传址Q?br /> 在学?fn)C++的时候我们都知道有两U参C递方式:(x)传值和传址。而在python中所有的参数传递都是引用传递(pass referenceQ,也就是传址。这是由于名字是对象的一个引用这一python的特性而自然得来的Q在函数体内部对某一外部可变对象作了(jin)修改肯定?x)将其改变带到函C外。让我们来看看下?br />q个例子Q?/p>
?.1 因此Q在python中,我们应该抛开传递参数这U概念,时刻牢记函数的调用参数是对象用另外一个名字空间的名字l定。在函数中,不过是用?jin)另外一个名字,但还是对q同一个对象进行操作?/p>
5.2 ~省参数 ?.2 Z(jin)什么问题?q个参数par好像cM与C中的?rn)态变量,累计?jin)以前的l果。是q样吗?当然不是Q这都是“对象、名字、绑定”这些思想惹的“祸”。“万物皆对象”,q记得吗Q这里,函数foo当然也是一个对象,可以UC为函数对象(与一般的对象没什么不同)(j)。先来看看这个对象有些什么属性?/p>
>>> dir(foo) 单从名字上看Q“func_defaults”很可能与缺省参数有养I看看它的倹{?/p>
>>> foo.func_defaults # 昄q个属性的内容 果不其然Q就是这个序列对象(tuple)包含?jin)所有的~省参数。验证一下:(x)
>>> def fooM(par1, def1=1, def2=[], def3='str'): # 定义一个有多个~省参数的函?br />... def2.append(0) 在函数定义中有几个缺省参敎ͼfunc_defaults中就?x)包括几个对象,暂且UC为缺省参数对象(如上列中?Q[]?str'Q。这些缺省参数对象的生命周期与函数对象相同,从函C用def定义开始,直到其消亡(如用delQ。所以即便是在这些函数没有被调用的时候,但只要定义了(jin)Q缺省参数对象就?x)一直存在?/p>
前面讲过Q函数调用的q程是对象在另外一个名字空间的l定q程。当在每ơ函数调用时Q如果没有传递Q何参数给q个~省参数Q那么这个缺省参数的名字׃(x)l定到在func_defaults中一个对应的~省参数对象上?br />>>> fooM(2) 函数foo改进一下,可能?x)更?gu)帮助理解Q?br />>>> def foo(par=[]): Z(jin)预防此类“问题”的发生Qpython采用下列Ҏ(gu)Q?br />>>> def foo(par=[]): 使用None作ؓ(f)哨兵Q以判断是否有参C入,如果没有Q就新创Z个新的列表对象,而不是绑定到~省 6.ȝ 7.参考资?br /> * 《Dive Into Python》,Mark PilgrimQ?a >http://diveintopython.org, 2003?br /> * 《Python Objects》,Fredrik LundhQ?a >http://www.effbot.org/zone/python-objects.htm?br /> * 《An Introduction to Python》,David M. BeazleyQ?a >http://systems.cs.uchicago.edu/~beazley/tutorial/beazley_intro_python/intropy.pdf?br /> * 从Python官方|站Q?a >http://www.python.orgQ上可以?jin)解到所有关于Python的知识?br /> posted on 2005-06-25 10:41 I love linux 阅读(670) 评论(2) ~辑 收藏收藏?65Key 所属分c? Python 因此Q在python中,我们应该抛开传递参数这U概念,时刻牢记函数的调用参数是对象用另外一个名字空间的名字l定。在函数中,不过是用?jin)另外一个名字,但还是对q同一个对象进行操作? a=a+1 已经是另一?引用"? The yield statement is only used when defining a generator function, and is only used in the body of the generator function. Using a yield statement in a function definition is sufficient to cause that definition to create a generator function instead of a normal function.
When a generator function is called, it returns an iterator known as a generator iterator, or more commonly, a generator. The body of the generator function is executed by calling the generator's next() method repeatedly until it raises an exception.
When a yield statement is executed, the state of the generator is frozen and the value of expression_list is returned to next()'s caller. By ``frozen'' we mean that all local state is retained, including the current bindings of local variables, the instruction pointer, and the internal evaluation stack: enough information is saved so that the next time next() is invoked, the function can proceed exactly as if the yield statement were just another external call.
The yield statement is not allowed in the try clause of a try ... finally construct. The difficulty is that there's no guarantee the generator will ever be resumed, hence no guarantee that the finally block will ever get executed.
If no expressions are present, raise re-raises the last exception that was active in the current scope. If no exception is active in the current scope, a TypeError exception is raised indicating that this is an error (if running under IDLE, a Queue.Empty exception is raised instead). Otherwise, raise evaluates the expressions to get three objects, using If the first object is an instance, the type of the exception is the class of the instance, the instance itself is the value, and the second object must be If the first object is a class, it becomes the type of the exception. The second object is used to determine the exception value: If it is an instance of the class, the instance becomes the exception value. If the second object is a tuple, it is used as the argument list for the class constructor; if it is If a third object is present and not The try statement specifies exception handlers and/or cleanup code for a group of statements:
There are two forms of try statement: try...except and try...finally. These forms cannot be mixed (but they can be nested in each other).
The try...except form specifies one or more exception handlers (the except clauses). When no exception occurs in the try clause, no exception handler is executed. When an exception occurs in the try suite, a search for an exception handler is started. This search inspects the except clauses in turn until one is found that matches the exception. An expression-less except clause, if present, must be last; it matches any exception. For an except clause with an expression, that expression is evaluated, and the clause matches the exception if the resulting object is ``compatible'' with the exception. An object is compatible with an exception if it is either the object that identifies the exception, or (for exceptions that are classes) it is a base class of the exception, or it is a tuple containing an item that is compatible with the exception. Note that the object identities must match, i.e. it must be the same object, not just an object with the same value. If no except clause matches the exception, the search for an exception handler continues in the surrounding code and on the invocation stack.
If the evaluation of an expression in the header of an except clause raises an exception, the original search for a handler is canceled and a search starts for the new exception in the surrounding code and on the call stack (it is treated as if the entire try statement raised the exception).
When a matching except clause is found, the exception's parameter is assigned to the target specified in that except clause, if present, and the except clause's suite is executed. All except clauses must have an executable block. When the end of this block is reached, execution continues normally after the entire try statement. (This means that if two nested handlers exist for the same exception, and the exception occurs in the try clause of the inner handler, the outer handler will not handle the exception.)
Before an except clause's suite is executed, details about the exception are assigned to three variables in the sys module: The optional else clause is executed if and when control flows off the end of the try clause.7.1 Exceptions in the else clause are not handled by the preceding except clauses. The try...finally form specifies a `cleanup' handler. The try clause is executed. When no exception occurs, the finally clause is executed. When an exception occurs in the try clause, the exception is temporarily saved, the finally clause is executed, and then the saved exception is re-raised. If the finally clause raises another exception or executes a return or break statement, the saved exception is lost. A continue statement is illegal in the finally clause. (The reason is a problem with the current implementation - this restriction may be lifted in the future). The exception information is not available to the program during execution of the finally clause. When a return, break or continue statement is executed in the try suite of a try...finally statement, the finally clause is also executed `on the way out.' A continue statement is illegal in the finally clause. (The reason is a problem with the current implementation -- this restriction may be lifted in the future). IBM developerWorks 提供?jin)三U下载方法:(x)FTP、HTTP 以及(qing)用于大文件下载的下蝲助手Q?Download DirectorQ。大多数情况下,FTP 要比 HTTP 更可靠,q可~短下蝲旉。最新的览器在q行 FTP 下蝲时会(x)昄旉估计和传输速度。在有些情况下,览器还可以l传中断?FTP 下蝲。要利用 FTP 的这U方便性,在?HTTP 下蝲之前首先试一?FTP 下蝲方式?/p>
如果(zhn)?FTP I过防火墙下载时遇到?jin)问题,再试?HTTP 下蝲。虽然?HTTP 方式q行大文件下载时不如 FTP 可靠Q但 Internet Explore ?Eclipse IDE ?Apache Ant 构徏工具q行 Python 开?/p>
U别: 初
Ron Smith
, 负责?br /> 2004 q?6 ?01 ?/p>
多年以来Q?Java 语言?Python 阵营之间一直存在大量的异花授粉现象。在q方面作出突?gu)率的可能?Jython。这是一个纯_用 Java 实现?Python q行时环境。按照这一说法Q?zhn)研I如何用 Eclipse IDE ?Ant 构徏与部|工具实?Python 开发。Eclipse ?Ant 是非常流行的工具Q它们特性丰富、可扩展性强、而且开放源代码QPython 也具有相同的品质。PyDev ?PyAntTasks 分别?Eclipse ?Ant 的扩展,有了(jin)它们可能用q些 Java 工具开?Python。本文从下蝲安装所需的工具与扩展开始讲赗ؓ(f)?jin)解释如何?Python 开发中使用 Eclipse ?AntQ我用实际?Python 代码例子d RSS 资源? 本文不会(x)涉及(qing) Eclipse、Ant、Python 的细节。有兌些话题的深入讨论Q请参阅 参考资?/font> 一节中的链接? 本文用到的Y仉?CPython 2.3 下测试过。除?jin)几个异常情况之外,应该也能?Jython 中运行。特别需要指出,PyDev 调试器目前不支持 Jython。另一个区别是通过 Jython 执行的脚本在?PyDev 中运行之后就转入交互模式Q这样就必须手动杀歅RPyDev ~辑器与 Jython 的源代码兼容QPython Ant d?py-doc d之外也和 Jython 兼容? Eclipse 是一?Java 技术集成开发环境,?IBM 开发,q开攑օ源代码。它?IBM 商业软g WebSphere Application Development 环境以及(qing)其他多种工具的基。Eclipse 的开发社区非常活跃,他们不仅开?Eclipse 本nQ还开发大量的插g?Eclipse 使用。有?Eclispe ?Eclipse 插g?Web 站点Q请参阅 参考资?/font> 一节中的链接。尽从传统上讲 Eclipse 是一U?Java 开发工P但是一些插件的存在使得?Eclipse 中开发其他语a的程序成为可能,?C/C++、Python ?Perl? ?Eclipse 中,源代码被l织到项目(projectQ中。项目可以加载、卸载和导入。Eclipse 用户界面的结构划分ؓ(f)视图QViewQ与~辑器(EditorQ。视图与~辑器的例子包括Q源代码大纲视图、Java 源代码编辑器、Python 源代码编辑器和文件系l导航视图。Eclipse 用户界面中最关键的隐含概念就?视角QperspectiveQ?/i>。视角是通常在执行某U类型活动时一起用的一l视图。Eclipse 中的标准视角包括QDebug、Java Browsing、Java、Java Type Hierarchy、Plug-in Development、CVS Repository Exploring、Resource ?Install/Update。目前还不存在单独的 Python 视角。在q行 Python 开发时Q我通常使用 Resource 视角?Debug 视角? 首先Q从 Eclipse Web 站点上下?EclipseQ请参阅 参考资?/font> 一节中的链接)(j)QƈҎ(gu)(zhn)的q_Q按照下面的安装指南安装 EclipseQ? Eclipse 的更新机制 PyDev 插g的安装更加容易。从 Eclipse 中选择 Help > Software Updates > Update ManagerQ启?Install/Update 视角。在左下角的 Feature Updates 视图中,?PyDev 插g更新站点作ؓ(f)新的 Site Bookmark d到“Sites to Visit”文件夹下。Eclipse ?PyDev 更新站点 URL ?http://pydev.sf.net/updates/。现在,Feature Updates ~辑器中应该昄出“PyDev”这一Ҏ(gu)。在 Feature Updates ~辑器中Q展开 PyDev > OtherQ选择其中昄?PyDev Ҏ(gu)(臛_应该?0.4.1Q。然后选择 “Install Now”安装该Ҏ(gu)。Eclipse 下?PyDev 插gQƈ其安装?Eclipse 中? 问本目中用的样例代码Q可先下?zip 文gQ请参阅 参考资?/font>一节)(j)Q在文gpȝ中展开?zip 文gQ然后将其中的项目导?Eclipse。导入项目的Ҏ(gu)是先切换?Resource 视角Q选择 File > ImportQ再选择“Existing Project into Workspace”,然后选择(zhn)展开 zip 文g的位|。这ӞNavigator 视图中应该出?feedParserTest 目? 样例目中已l包含了(jin) Fead Parser 通用资源解析库,该库?Python 开放源代码许可协议发布。有?Feed Parser 目 Web |站的链接,请参?参考资?/font> 一节? 现在开始学?fn)如何通过已导入的目?jin)?PyDev 的特性。PyDev 正处于开发过E中Q但已经是非帔R效的 Python 开发环境。现在的 PyDev 主要包括以下Ҏ(gu):(x) 通过 Window > PreferencesQƈ选择 PyDevQ请参阅?1Q,便可讉K PyDev 选项。第一l选项可以改变 PyDev 在源代码中处理制表符的方式,q可以改变语法元素的颜色? PyDev Debug 选项可以选择 Python 解释器,供执?Python 代码时用。如?PyDev 无法扑ֈ Python 解释器,或者想使用别的解释器,可在此设|(请参阅图 2Q? 我的大部?Python 工作都是?Resource 视角中完成的。用方法是先切换到 Resource 视角Q然后在左上角的 Navigator 视图中双?feedParserTest/src/feedparserTest/FeedparserTest.py 文g。Python ~辑器打开该文Ӟ?Python 语法q行解析Q完成设|颜色和语法(g)查的工作Q请参阅?3Q? 如果源代码中有Q何错误,则显C在右下角的 Tasks 视图中显C出来。双?Tasks 视图中的错误Q便可找到那条讨厌的代码行? Outline 视图在左下角Q其中用一U便于浏览的l构昄出当前正在编辑的文g。导入的库、类、函数全都显C出来,通过双击 Outline 视图中的目Q便可以实现D。PyDev 在编?Python 文g的过E中寚wq行预先解析的工作,同时更新 Outline 视图Q执行语法检查,q用不同颜色昄语法元素? PyDev 0.4 版在 Python 源代码编辑器中ؓ(f)函数和导入库加入?jin)超链接的特性。如果在过某项导入或函数调用(必须? Z已经开始将一些优异的源代码编辑特性加入最新版本的 PyDev 中,其中包括代码块注释与取消注释,以及(qing)代码左右UMQ请参阅?4Q? 如果不能执行代码Q那?IDE 也不是太有用。ؓ(f)执行 Python 代码Q可?Navigator 视图中选择 feedparser.py 文gQ用右键点击Q然后选择 Python > Run。随后会(x)昄 Python 的启动配|窗口(请参阅图 5Q? Python 启动配置H口中可以定义脚本执行的当前目录Q传递给脚本的参敎ͼ以及(qing)用哪一?Python 解释器运行脚本。feedparser.py 以一?RSS URL 作ؓ(f)参数Q所以可在参数字D中填入 URLQ如 http://www.ibm.com/developerworks/news/dw_dwtp.rss。其余的~省定义可以了(jin)Q所以单?Run? 脚本执行时输Z息显C在 Console H口中。如果有错误出现QConsole H口中将昄堆栈跟踪信息Q其中的每一行都可以通过链接找?Python 源代码? Python 调试器是最q才加入 PyDev 插g中的。要使用调试器,可在 Python ~辑器中想中断的代码行的左侧点击Q设|断炏V在?6 中,我在 feedparser.py ?1830 行处讄?jin)断炏V然后在 Navigator 视图中选择q个 Python 模块Q点d键,选择“Python > Debug...”。这时将昄与前面相似的一个启动配|窗口。点?Debug q入 Debug 视角Q同时启动调试器? 左上角的 Debug 视图昄当前正在执行的进E和U程Q右上角?Variables 视图昄当前q行域中的所有变量,Python ~辑器会(x)昄调试器目前停在哪条语句上Q同时所有的输出信息都显CZ Console 视图中。调试器可以通过 Debug 视图底部的按钮或 Run 菜单q行控制? Eclipse ?qing)其插gq具备很多其他的Ҏ(gu),可应用于 Python 开发中Q如 XML ~辑器、UML ~辑器(不过大多数是?Java 代码Z?j)?j)Q还有资源控制方面的插g。目?Eclipse 插g站点上列出的插g几乎?500 个(请参?参考资?/font> 一节中的相关链接)(j)。我着重介l一个对很多 Python 开发h员都特别有用的插Ӟ(x)Eclipse 发行版中已经包括?CVS 插gQ不q不?x)讨论细节内宏V? Eclipse 中包括特性丰富的集成 CVSQ?/p>
q可以通过提供其他插g来支持其他源代码控制pȝQ如 ClearCase、Subversion、Visual SourceSafe {? Python 解释器支?Python 代码的交互式执行。这U方式对于调试一D代码是非常有用的,因ؓ(f)不用把代码放q?Python 脚本中ƈ执行脚本?jin)。同ӞPython 解释器的交互模式可以很容易地集成?Eclipse 中? 要增加对 Python 交互式执行的支持Q可通过 Run > External Tools > External Tools 增加一?External Tool 启动E序。这时将打开 External Tool 启动E序配置H口。在 Configurations 列表中选择“Program”,然后点击“New”创Z个新的配|。将该配|命名ؓ(f)诸如 "pythonInteractive" 之类Q然后设|?LocationQo(h)其指向?zhn)?Python 解释器,接着Q将 "-i" 作ؓ(f)唯一的参C递进来(请参阅图 7Q? ?Common 选项卡下Q选中复选框Q该配|在 External Tools 收藏夹菜单中昄出来? 要运行刚刚在 Eclipse 中创建的启动器,可选择 Run > External Tools > pythonInterpreter。Python 解释器的输出昄?Console 视图中。Console 中可输入 Python 命o(h)q执行,像从命令行中执?Python 一栗ؓ(f)导入q在交互模式下用模块,(zhn)需要将模块的位|增加到 ?Eclipse Console 中执?Python 与用命o(h)行执行的不同之处在于Q无法启用命令历史特性(通过向上和向下的方向键实玎ͼ(j)Q因?Eclipse Console ?x)自p释这些键? Python ?x)在它需要的时候自动编译模块。这意味着 Python 开发h员通常不必昑ּ地对模块q行~辑。即便如此,有时候手工编?Python 代码q是很有用的Q同Ӟ构徏和部|过E中q有很多其他斚w的内容可以自动化实现。这也正是构建工L(fng)用武之地? 我将着重介l来?Java ~程世界中的 Apache AntQ这个工具可大量应用?Python 开发中。Apache Ant ?Java ~程领域内事实上的标准构建工兗它更加MQ与 Java 技术结合得更好Q可用于替代其他的构建工兗Ant 可以在支?Java ~程语言的Q何一U^Cq行。尽我们需要的大多数构建特?Ant 都已l提供了(jin)Q但如果要将 Ant 用做 Python 构徏工具Q还是需要有一些关键的?Python 相关的特性。我已经开发了(jin)若干定制?Ant 插gQ用 Ant 的行话讲叫做 taskQ,可提供构?Python 旉要的特定?Python 的特性? Ant ?XML 作ؓ(f)描述构徏的格式。build 文gl织为需要执行的目标。每一个目标都可能依赖于其他的目标。Ant 根据?zhn)所h执行的目标,以及(qing)一l依赖目标,来执行Q何需要的目标。每一个目标都可能包含L数量?Ant dQ而由 Ant d实际执行目标的工作。Ant 有很多内|的dQ可以完成诸如编?Java 代码、生成文档、操U|件和目录Q同时第三方又提供了(jin)很多附加的Q务? 我将通过?feedparser 目创徏构徏脚本来介l?Ant 构徏脚本?Python Ant d的基知识。ؓ(f)?jin)?Python Ant dQ?zhn)需要下载ƈ安装包含q些d?Java 库。首先,?参考资?/font> 一节中列出?URL 中下?Python Ant d库(pyAntTasks.jarQ。然后,?JAR 文g拯?Eclipse ?Ant 插g下的 lib 目录中。这应该?Eclipse 安装目录下Ş?plugins/org.apache.ant_1.5.3 的子目录? Python Ant d库拷贝完毕之后,必须?Eclipse 中启用库。选择 Window > PreferencesQ然后选择 Ant > Runtime。将 Ant Home Entries 展开Q其中可看到 Eclipse 使用的库QJAR 文gQ列表。选择?Add JAR”,然后?Eclipse Ant 插g?lib 目录中选择 Python Ant JAR 文gQ就可以刚刚拷贝的 Python Ant JAR 文g加入库列表中Q请参阅?8Q? (zhn)现在应该能够创建和q行包含 Python d?Ant 构徏脚本?jin)。下面进入构本内部! 我将逐步介绍如何创徏一个简单的 Python 构徏脚本Q请参阅清单 1Q。完整的构徏脚本 build.xml 可从 feedParserTest 目的顶层目录中扑ֈ? 先介l一个只~译 Python 样例代码的构本?lt;project> 标签L构徏脚本的根标签?lt;taskdef> 标签声明在整个构本中使用?Python d。在构徏脚本的底部,可以定义 要运行构本,可从 Eclipse 中打开它。Eclipse h内置?Ant 构徏脚本~辑和浏览功能。Outline 视图可以昄出构本的l构。在 Navigator 视图中,选择该构本,用右键点击,然后选择“Run Ant...”。选择 接下来将向构本中加入新的目标Q用于执?Python 脚本Q请参阅清单 2Q。在本例中,可以?RSS URL 作ؓ(f)参数来执?feedparser.py 脚本? 上面的目标以 RSS URL 为唯一的参数来执行 feedparser.py 脚本。该目标声明Z赖于 Python ?API 文~制机制?Java 技术中?JavaDoc pȝcMQ称?PyDoc。在构徏脚本中加入清?3 中列出的如下 XML 片断Q可为所有的 Python 模块生成 PyDoc?
W?8 行开始是 py-doc d。如前所qͼ(zhn)传入生?pydoc q程中所使用? W?9 至第 11 行定义了(jin)在生成文档的q程中应该处理哪?Python 源文件。文仉?Ant 脚本中通用的结构,可用于定义所操作的一l文件。这是一U很强大的特性,它(zhn)能够通过名字模式、布?yu)(dng)逻辑和文件属性来选择所要操作的文g。Ant 文中有q方面的完整描述。本例中递归选择?jin)“src”目录下的所有文件? Python 中具有标准的单元试框架Q从 Python 2.3 开始。在 Python 2.2 中这只是可选模块)(j)Q与 Java jUnit 框架十分cM。测试用例的l构?jUnit 采用相同的方式。每一个待试的类和模块通常都具有自q试cR测试类中包含测试装|(fixtureQ,它们? 上述清单是实?feedparser 模块基本试功能的测试类。完整的试c见 feedParserTest 目下的 src/feedparserTest/FeedparserTest.py? 要独立运行该试c,可以按前面所说的相同方式q行 FeedparserTest.py 模块。在 Eclipse Navigator 视图中选择 FeedparserTest.pyQ然后通过 Python > Run q行。此时显C启动配|窗口。除 Base 目录之外Q其他都保持~省值即可。Base 目录必须?feedParserTest 目的目录,q样才能在当前目录下扑ֈ RSS 文gQtestData/developerworks.rssQ。修?base 目录的设|,然后点击“Run”。输Z息显C在 Console 上? (zhn)也许希望我们编写的所有单元测试都能够作ؓ(f)构徏的一部分自动执行。将下面清单 5 所C的构徏片断加入构徏脚本便可实现? W一行是目标声明Q这与其他的脚本相同。第 2 至第 6 行调?py-test d。这部分代码在“src”目录下查找所有以“Test.py”结所有文Ӟq运行所有测试? q行目标的方法是先运行构本,再选择执行“tests”目标。该目标运行所有以“Test.py”结试用例Q本例中仅有 FeadparserTest.py? Eclipse ?PyDev 插g的结合,以及(qing) Apache Ant ?Python Ant d一起用,可以?Python 开发提供完全集成的开发环境和构徏/部v工具。这些工具尚在开发过E中Q因此要l常查看是否有更斎ͼ如果(zhn)觉得特别希望看到某U特性,可以卯v袖管自力更生?
Ron Smith ?RPS Technologies, Inc 的创始h。这是一家Y件开发与软gN公司Q总部位于芝加哥地区。Ron Smith 为客h供基?J2EE 的企业应用程序发斚w的咨询,同时也在 RPS Technologies 内部开发Y件品。可以通过 ron.smith@rpstechnologies.net?Ron 联系?
python的对象与名字l定Q{_(d)此文甚好Q?/a>
i = 1
“符D句是用来名字绑定(或重新绑定)(j)到某个对象的操作Q而且它也可用来修改可变对象的属性或
对象中所包含的成员。?/p>
>>> b = a*4
>>> print b
[{'g': 1}, {'g': 1}, {'g': 1}, {'g': 1}]
>>> b[0]['g'] = 2
>>> print b
“万物皆对象?Everything is object)Q这是pythonq种面向对象语言所倡导的理c(din)在我们熟?zhn)的C++中,1只是一个整型数Q而不是一个对象。但在python中,1却是一个实实在在的对象Q?zhn)可以用dir(1)来显C它的属性?/p>
* 唯一的标识码(identity)
* cd
* 内容Q或UCؓ(f)|(j)
pass
...
>>> obj = c1()
>>> obj
<__main__.c1 instance at 0x00AC0738>
>>> id(obj)
11274040
7957136
其结果是FalseQ是因ؓ(f)q是两个不同的对象,存储在内存中的不同地斏V?/font>
其结果是TrueQ是因ؓ(f)q两个不同的对象有着相同的倹{?/font>
* 没有或者拥有多个方?br /> * 没有或者有多个名字
名字是对一个对象的U呼Q一个对象可以只有一个名字,也可以没有名字或取多个名字。但对象自己却不知道有多名字,叫什么,只有名字本n知道它所指向的是个什么对象。给对象取一个名字的操作叫作命名Qpython赋D句认为是一个命名操作(或者称为名字绑定)(j)?/p>
3. l定
如上所讲的Q绑定就是将一个对象与一个名字联pv来。更切地讲Q就是增加该对象的引用计数。众所周知QC++中一大问题就是内存泄?-- 卛_态分配的内存没有能够回收Q而解册一问题的利器之一是引用计数。python采用了(jin)q一技术实现其垃圾回收机制?br />
python中的所有对象都有引用计数?/p>
引用计数减一?br />* "i"所指向的老对象的值ƈ没有改变?br />* q就是ؓ(f)什么在python中没?+?-q样的单目运符的一个原因?/p>
对象的引用计数在下列情况下会(x)增加Q?br /> * 赋值操?br /> * 在一个容器(列表Q序列,字典{等Q中包含该对?/p>
* 对象的一个名字被l定到另外一个对?br /> * 对象从包含它的容器中U除
* 名字被显C地用del销毁(如:(x)del iQ?/p>
>>> li2 = li1
>>> li1[1] = 16
>>> print li2
[7, 16, 9, 10]
>>> print b
[{'g': 1}, {'g': 1}, {'g': 1}, {'g': 1}]
>>> b[0]['g'] = 2
>>> print b
[{'g': 2}, {'g': 2}, {'g': 2}, {'g': 2}]
>>> print b
[{'g': 1}, {'g': 1}, {'g': 1}, {'g': 1}]
>>> b[0]['g'] = 2
>>> print b
[{'g': 2}, {'g': 1}, {'g': 1}, {'g': 1}]
>>> b = [a]*4
>>> b[0]['g'] = 2
>>> print b
[{'g': 2}, {'g': 2}, {'g': 2}, {'g': 2}]
>>> print a
{'g': 2}
>>> b = [a] + [a] + [a] + [a]
>>> b[0]['g'] = 2
>>> print b
[{'g': 2}, {'g': 2}, {'g': 2}, {'g': 2}]
>>> print a
{'g': 2}
>>> a = [1, 2, 3]
>>> def foo(par):
... par[1] = 10
...
>>> foo(a)
>>> print a
[1, 10, 3]
使用~省参数Q是我们喜爱的一U作法。这可以在调用该函数时节省不的击键ơ数Q而且代码也显得更加简z。更重要的是它从某种意义上体C(jin)q个函数设计的初街?br /> 但是python中的~省参数Q却隐藏着一个玄机,初学者肯定会(x)在上面栽跟头Q而且q个错误非常隐秘。先看看下面q个例子Q?/p>
>>> def foo(par=[]):
... par.append(0)
... print par
...
>>> foo() # W一ơ调?br />[0]
>>> foo() # W二ơ调?br />[0, 0]
['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__', '__getattribute__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']
([0, 0],)
>>> foo() # W三ơ调?br />[0, 0, 0]
>>> foo.func_defaults # 再来看看q个属?br />([0, 0, 0],)
... print par1, def1, def2, def3
...
>>> fooM.func_defaults
(1, [], 'str')
函数fooM内的名字def1׃(x)l定到func_defaults中的W一个对象,def2l定到第二个Qdef3则是W三个?br />所以我们看到在函数foo中出现的累加现象Q就是由于parl定到缺省参数对象上Q而且它是一个可变对象(列表Q,par.append(0)׃(x)每次改变q个~省参数对象的内宏V?/p>
... print id(par) # 查看该对象的标识?br />... par.append(0)
... print par
...
>>> foo.func_defaults # ~省参数对象的初始?br />([],)
>>> id(foo.func_defaults[0]) # 查看W一个缺省参数对象的标识?br />11279792 # 你的l果可能?x)不?br />>>> foo()
11279792 # 证明parl定的对象就是第一个缺省参数对?br />[0]
>>> foo()
11279792 # 依旧l定到第一个缺省参数对?br />[0, 0] # 该对象的值发生了(jin)变化
>>> b=[1]
>>> id(b)
11279952
>>> foo(b) # 不用缺省参?br />11279952 # 名字par所l定的对象与外部名字b所l定的是同一个对?br />[1, 0]
>>> foo.func_defaults
([0, 0],) # ~省参数对象q在那里Q而且值ƈ没有发生变化
>>> foo()
11279792 # 名字par又绑定到~省参数对象?br />([0, 0, 0],)
... if par is None:
... par = []
... par.append(0)
... print par
参数对象上?/p>
* python是一U纯_的面向对象语言?br /> * 赋D句是名字和对象的l定q程?br /> * 函数的传参是对象C同名字空间的l定?/p>
评论
re: python的对象与名字l定Q{_(d)此文甚好Q?2005-12-28 16:43 jarodzz
def foolyou(a):
a=a+1
if __name__=='__main__':
b=1
foolyou(b)
print b
what is b now? 回复
re: python的对象与名字l定Q{_(d)此文甚好Q?a name="Post">2006-01-04 16:15 asdf_asdf
>>> def foolyou(a):
print id(a)
a=a+1
print id(a)
>>> b
1
>>> foolyou(b)
148479408
148479396
>>> id(b)
148479408 回复
]]>
]]>
[3*x for x in vec if x > 3]
[x*y for x in vec1 for y in vec2]
......
there expression can used to instead the functional programming tools such as map() ,filter(),reduce()..
Note Two : Some functions in the modules often be made used of
1.strip() : Return a copy of the string s with leading and trailing whitespace removed.
>>> test_str = ' I Love Python '
>>> string.strip(test_str)
'I Love Pyhon' Note that : whitespace at the two side of the string were removed ,but it did not worked on the whitespace between string!
2. str() : can convert the format like int ,long , float ... into string format
>>> num_1 = 3.14
>>> num_2 = 0.618
>>> str(num_1) , str(num_2)
'3.14' '0.618'
3.dict()
dict() -> new empty dictionary.
dict(mapping) -> new dictionary initialized from a mapping object's
(key, value) pairs.
dict(seq) -> new dictionary initialized as if via:
d = {}
for k, v in seq:
d[k] = v
dict(**kwargs) -> new dictionary initialized with the name=value pairs
in the keyword argument list. For example: dict(one=1, two=2)
e.g
dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
dict([(x, x**2) for x in (2, 4, 6)])
dict(sape=4139, guido=4127, jack=4098)
4. enumerate()
Return an enumerate object. iterable must be an other object that supports
iteration. The enumerate object yields pairs containing a count (from
zero) and a value yielded by the iterable argument. enumerate is useful
for obtaining an indexed list: (0, seq[0]), (1, seq[1]), (2, seq[2]), ...
Code show:
>>> for i, v in enumerate(['tic', 'tac', 'toe']):
... print i, v
...
0 tic
1 tac
2 toe
5 zip()
Return an enumerate object. iterable must be an other object that supports
iteration. The enumerate object yields pairs containing a count (from
zero) and a value yielded by the iterable argument. enumerate is useful
for obtaining an indexed list: (0, seq[0]), (1, seq[1]), (2, seq[2]), ...
Code Show:>>> 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.
6.sorted()
Code Show:>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> for f in sorted(set(basket)):
... print f
...
apple
banana
orange
pear
to be continued......
Note Three : simple statements
7 The yield statementgenerators
feature has been enabled. It will always be enabled in Python 2.3. This __future__
import statement can be used to enable the feature:
from __future__ import generators
8 The raise statementraise_stmt ::= "raise" [expression ["," expression ["," expression]]] None
as the value of omitted expressions. The first two objects are used to determine the type and value of the exception.
None
.
None
, an empty argument list is used, and any other object is treated as a single argument to the constructor. The instance so created by calling the constructor is used as the exception value.
None
, it must be a traceback object (see section 3.2), and it is substituted instead of the current location as the place where the exception occurred. If the third object is present and not a traceback object or None
, a TypeError exception is raised. The three-expression form of raise is useful to re-raise an exception transparently in an except clause, but raise with no expressions should be preferred if the exception to be re-raised was the most recently active exception in the current scope.
9 The try statementtry_stmt ::= try_exc_stmt | try_fin_stmt try_exc_stmt ::= "try" ":" suite ("except" [expression ["," target]] ":" suite)+
["else" ":" suite]
try_fin_stmt ::= "try" ":" suite "finally" ":" suite sys.exc_type
receives the object identifying the exception; sys.exc_value
receives the exception's parameter; sys.exc_traceback
receives a traceback object (see section 3.2) identifying the point in the program where the exception occurred. These details are also available through the sys.exc_info() function, which returns a tuple (exc_type, exc_value, exc_traceback)
. Use of the corresponding variables is deprecated in favor of this function, since their use is unsafe in a threaded program. As of Python 1.5, the variables are restored to their previous values (before the call) when returning from a function that handled an exception.
]]>
]]>
头疼?jin)很?eclipse中无法正常更新pydev。我又回头检查,域名是正的Q但是还是出现错误?br />想了(jin)很久Q在|上到处扑օ于此c问题的文章Q但是收获不大,可以说几乎找不到之类文章?br />q运的事 Q我正在L其他插g时候和察看其他python开发工L(fng)时候,无意中点Z(jin)IBM 的下面这个页面?br />时我就恍然大?zhn)Q才发现无法更新的原因:(x)
因ؓ(f)公司的封掉了(jin)几个端口Q防止用非工作范围内的׃软g或其他的聊天软gQ?br />而eclipse的更新模式基于基于FTP模式的?br />当然q是造成无法更新的原因之一Q可能还有其他原因但是我没想刎ͼ也没遇见q?br />
quote:
下蝲Ҏ(gu)QFTP、HTTP 和下载助?/span>
r 5.01 ?qing)以上版本有时能够恢复中断?HTTP 下蝲。HTTP 下蝲能够I过防火墙,因ؓ(f)它用了(jin)端口?80 来进行数据传输。以下下载行为和错误可能是遇C(jin)防火墙问题:(x)
]]>
?Eclipse ?Ant q行 Python 开?/h1>
文选项
最新推?/td>
Python 是一U非常灵zd大的动态脚本编E语aQ具有完整的面向对象Ҏ(gu)。众多的支持者指出,Python 语言与其他语a相比能更快更有效地表辑և他们的意图。但是从 Java 技术™ ?Microsoft] .NET 刚刚转到 Python 的h?x)发玎ͼ功能丰富而精致的 IDE 和开发工具都不见?jin)。那些开发h员可以从他们熟?zhn)?Java 开发工具中扑ֈ解决Ҏ(gu)。本文着重介l了(jin)如何使用Z Java 技术的行开发工?Eclipse ?Ant q行 Python 开发?/blockquote>
回页?/font>
回页?/font>
?1. PyDev 选项H口
?2. PyDev Debug 选项
?3. Python ~辑?/b>
PYTHONPATH
目录中)(j)的同时按?Control 键,PyDev p昄Z个超链接Q这h可以在导入库或函数的源代码之间导航。请注意Qؓ(f)?jin)在?zhn)自q源代码中跨模块用该Ҏ(gu)(从一个模块链接到另一个模块)(j)Q必M?PYTHONPATH
环境变量Q在其中加入q些模块Q这?PyDev 可以找到它们了(jin)?
?4. PyDev ~辑器的其他Ҏ(gu)?/b>
?5. Python 启动配置
?6. Python 调试?/b>
回页?/font>
?7. Python 交互方式配置
PYTHONPATH
环境变量中?
回页?/font>
?8. ?classpath 中加?Python Ant d
清单 1. 用于~译 Python 源代码的构徏脚本片断
<project name="feedParserTest" default="compile">
<taskdef resource="pyAntTasks.properties"/>
<property name="src.dir" value="src"/>
<target name="compile">
<py-compile dir="${src.dir}" pythonpath="${src.dir}" optimize="0"/>
</target>
</project>
compile
目标。目标元素内部是 compile
q行期间执行的Q务。特别的?py-compile dQ它负责?src 目录开始,~译所有的 Python 代码。该d?x)递归遍历所有的子目录,q编译所有的 Python 模块。脚本中没有采用?src 目录编码到调用之处的方式,而是在构本中定义?jin)称?src.dir 的属性。然后,在需要用这个目录名的时候,可以通过 ${src.dir}
来引用?compile
目标Q然后点几ZRun”。构本执行过E中的输Z息应该显C在 Console 视图中,表示q行成功?
清单 2. q行 feedparser 脚本的构本片?/b>
<target name="run.feedparser" depends="compile">
<py-run script="src/feedparser/feedparser.py" pythonpath="${src.dir}" optimize="0">
<arg value="http://www.ibm.com/developerworks/news/dw_dwtp.rss">
</py-run>
</target>
compile
目标Q所以后者将首先执行。实际上q一步ƈ不是很必要,因ؓ(f) Python ?x)根据需要自动编译源代码。如果?zhn)执?run.feedparser
目标Q就?x)运?feedparser.py 脚本Q同时将 RSS 的内容输出到 Console 中?
清单 3. 用于生成 PyDoc 的构本片?/b>
1: <property name="pydoc.dir" value="pydoc"/>
2:
3: <target name="init">
4: <mkdir dir="${pydoc.dir}"/>
5: </target>
6:
7: <target name="pydoc" depends="init,compile">
8: <py-doc pythonpath="${src.dir}" destdir="${pydoc.dir}">
9: <fileset dir="${src.dir}">
10: <include name="**/*"/>
11: </fileset>
12: </py-doc>
13: </target>
从对上述 pydoc 目标的解析可看出Q第 7 行声明了(jin)目标名称Qƈ指出它依赖于
init
?compile
目标。这意味着在运?pydoc 目标之前QAnt 必须保证 init
?compile
目标已经q行Q如果没有,则首先运行这两个目标?pydoc
目标所依赖?init
目标在第 3 至第 5 行定义?init
目标仅仅创徏?jin)一个存?PyDoc API 文文g的目录。如前所qͼ要ؓ(f)所生成文的保存位|定义一个属性,名ؓ(f) pydoc.dir?PYTHONPATH
?destdir
属性告?py-doc d生成的 HTML 文档输出C处?setUp
函数中初始化。每一个测试都~写为测试类中的一个独立的试函数。unittest 框架?x)在试函数之间循环往复,先调?setUp
、再试函数、然后清除( tearDown
Q测试函数。请参阅清单 4 中的样例?
清单 4. Python 单元试模块
import unittest
from pprint import pprint
import feedparser
class FeedparserTest(unittest.TestCase):
"""
A test class for the feedparser module.
"""
def setUp(self):
"""
set up data used in the tests.
setUp is called before each test function execution.
"""
self.developerWorksUrl = "testData/developerworks.rss"
def testParse09Rss(self):
"""
Test a successful run of the parse function for a
0.91 RSS feed.
"""
print "FeedparserTest.testParse09RSS()"
result = feedparser.parse(self.developerWorksUrl)
pprint(result)
self.assertEqual(0, result['bozo'])
self.assert_(result is not None)
channel = result['channel']
self.assert_(channel is not None)
chanDesc = channel['description']
self.assertEqual(u'The latest content from IBM developerWorks',
chanDesc)
items = result['items']
self.assert_(items is not None)
self.assert_(len(items)> 3)
firstItem = items[0]
title = firstItem['title']
self.assertEqual(u'Build installation packages with
solution installation and deployment technologies',
title)
def tearDown(self):
"""
tear down any data used in tests
tearDown is called after each test function execution.
"""
pass
if __name__ == '__main__':
unittest.main()
setUp
函数负责准备整个试q程中需要用的试装置Q在本例中只有测试用?RSS 文g的目录,试函数对其进行解析?testParse09Rss
是真正的试函数。这个函数调?feedparser.parse 函数Q传递测试用?RSS 文gQ输?gu)析结果,q过 TestCase cȝ assert 函数执行基本的检查统作。如果Q?assert 的求值结果不是真Q或是在执行q程中抛ZQ何异常,unittest ׃(x)报告一ơ测试失败或错误。最后的两行负责在这个测试类内部q行试Q方法是直接q行该模块即可?
清单 5. 执行单元试的构本片?/b>
1: <target name="tests" depends="compile">
2: <py-test pythonpath="${src.dir}" dir=".">
3: <fileset dir="${src.dir}">
4: <include name="**/*Test.py"/>
5: </fileset>
6: </py-test>
7: </target>
PYTHONPATH
讄为“src”,试执行的当前工作目录就是当前目录(?’)(j)?
回页?/font>
回页?/font>
回页?/font>
]]>
Note OneQabout sequences and lists
序列是不可变列表。一旦创Z(jin)一个序列就不能以Q何方式改变它?/font>
?1.21. 定义序列
>>>
t = ("a", "b", "mpilgrim", "z", "example")
>>>
t
('a', 'b', 'mpilgrim', 'z', 'example')
>>>
t[0]
'a'
>>>
t[-1]
'example'
>>>
t[1:3]
('b', 'mpilgrim')
?1.22. 序列没有Ҏ(gu)
>>>
t
('a', 'b', 'mpilgrim', 'z', 'example')
>>>
t.append("new")
Traceback (innermost last):
File "<interactive input>", line 1, in ?
AttributeError: 'tuple' object has no attribute 'append'
>>>
t.remove("z")
Traceback (innermost last):
File "<interactive input>", line 1, in ?
AttributeError: 'tuple' object has no attribute 'remove'
>>> t.index("example")
Traceback (innermost last):
File "<interactive input>", line 1, in ?
AttributeError: 'tuple' object has no attribute 'index'
>>>"z" in t
1
![]() |
你不能向序列增加元素。序列没?append ?extend Ҏ(gu)?/font> |
![]() |
你不能从序列中除掉元素。序列没?remove ?tt> pop Ҏ(gu)?/font> |
![]() |
你不能在序列中查扑օ素。序列没?index Ҏ(gu)?/font> |
![]() |
然而,你可以?in 来看一看是否一个元素存在于序列?/font>?/font> |
那么序列有什么好处呢Q?/font>
Note Two : Mapping in the Lists
列表映射介绍
>>> li = [1, 9, 8, 4]
>>> [elem*2 for elem in li]
[2, 18, 16, 8]
>>> li
[1, 9, 8, 4]
![]() |
Z(jin)对这一Ҏ(gu)一个感性认识,从右向左看它?li 是一个将要映的列表。Python循环遍历 li 一ơ一个元素,临时每个元素的Dl变?elem。然后Python使用函数 elem*2 Q接着结果追加到q回列表中?/font> |
![]() |
?font color="#ff0000">意列表映不改变被映的列表?/font> |
Python支持一U有的语法Q它允许你快速定义单行的最函数。这些叫?lambda 的函数是从Lisp中借用来的Q可以被用在M需要函数的地方?/font>
Z历史的原因,lambda 函数的语法与通常的函数有些细微的不同?/font>
?2.20. lambda 函数介绍
>>>
def
f(x):
...
return x*2
...
>>>
f(3)
6
>>>
g = lambda x: x*2
>>>
g(3)
6
>>>
(lambda x: x*2)(3)
6
MQ?lambda 函数是一个可以接收Q意多个参?包括 可选参?/font> )q且q回单个表达式值的函数?lambda 函数不能包含命o(h)Q它们所包含的表辑ּ不能过一个。不要试囑 lambda 函数中塞入太多的东西Q如果你需要更复杂的东西,应该定义一个普通函敎ͼ然后惌它多长就多长?/font>
![]() |
|
lambda 函数是风格问题。不一定非要用它们,M能够使用它们的地方,都可以定义一个分ȝ普通的函数Q用它来替换。我它们用在需要封装特D的Q非重用的代码上Q用许多的一行函C?x)弄乱我的代码?/font> |
?2.21. ?in apihelper.py 中的 lambda 函数
processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
Zq里有几件事情需要注意。首先,我们使用? and-or 技巧的单Ş式,没问题,因ؓ(f)一?lambda 函数 在一个布?yu)(dng)环境?/font> Mؓ(f)真?qƈ不意味着 lambda 函数不能q回假倹{函数本wL为真Q它的返回值可以ؓ(f)M倹{?
W二Q我们用了(jin) split 函数没带参数。你已经看到q它?/font> 1个或2个参?/font> 的用,但是不带参数它按I白q行分割?/font>
?2.22. split 不带参数
>>>s = "this is\na\ttest"
>>>print s
this is
a test
>>>print s.split()
['this', 'is', 'a', 'test']
>>>print " ".join(s.split())
'this is a test'
![]() |
q是一个多行字W串Q通过转义字符的定义代替了(jin) 三重引号 ?\n 是一个回车; \t 是一个制表符?/font> |
![]() |
split 不带参数按空白进行分剌Ӏ所以三个空|一个回车,和一个制表符都是一L(fng)?/font> |
![]() |
你可以将I白l一化,通过分割一个字W串Q然后用单个I格作ؓ(f)分隔W将光新接h。这是 help 函数所做的Q将多行文档字符串合q成单行?/font> |
那么 help 函数到底用这?lambda 函数Q?split 函数Q和 and-or 技巧做?jin)什么呢Q?
processFunc = collapse and (lambda s: " ".join(s.split())) or (lambda s: s)
processFunc 现在是一个函敎ͼ但它为哪一个函数要?collapse 变量的倹{如?collapse 为真Q?processFunc(string) 压~空白;否则Q?tt>processFunc(string) 返回未改变的参数?
在一个不很徏壮的语言实现它,象VBQ你可能创Z个函敎ͼ它接收一个字W串和一?collapse 参数Q用一?if 语句来判断是否要压羃I白或不压羃Q然后返回相应的倹{这h率低Q因为函数将不得不处理每U可能性;每次你调用它Q它?yu)不得不在给Z所惌的东西之前,判断是否要压~空白。在Python中,你可以将那种判断逻辑拿到函数外面Q而定义一个裁减过?lambda 函数来给出确切的(q且唯一)你想要的。这样做更有效率Q更漂亮Qƈ且更导致那些o(h)厌的(哦,惛_那些参数头?的错误?br />
This second tour covers more advanced modules that support professional programming needs. These modules rarely occur in small scripts.
The repr module provides an version of repr() for abbreviated displays of large or deeply nested containers:
>>> import repr >>> repr.repr(set('supercalifragilisticexpialidocious')) "set(['a', 'c', 'd', 'e', 'f', 'g', ...])"
The pprint module offers more sophisticated control over printing both built-in and user defined objects in a way that is readable by the interpreter. When the result is longer than one line, the ``pretty printer'' adds line breaks and indentation to more clearly reveal data structure:
>>> import pprint >>> t = [[[['black', 'cyan'], 'white', ['green', 'red']], [['magenta', ... 'yellow'], 'blue']]] ... >>> pprint.pprint(t, width=30) [[[['black', 'cyan'], 'white', ['green', 'red']], [['magenta', 'yellow'], 'blue']]]
The textwrap module formats paragraphs of text to fit a given screen width:
>>> import textwrap >>> doc = """The wrap() method is just like fill() except that it returns ... a list of strings instead of one big string with newlines to separate ... the wrapped lines.""" ... >>> print textwrap.fill(doc, width=40) The wrap() method is just like fill() except that it returns a list of strings instead of one big string with newlines to separate the wrapped lines.
The locale module accesses a database of culture specific data formats. The grouping attribute of locale's format function provides a direct way of formatting numbers with group separators:
>>> import locale >>> locale.setlocale(locale.LC_ALL, 'English_United States.1252') 'English_United States.1252' >>> conv = locale.localeconv() # get a mapping of conventions >>> x = 1234567.8 >>> locale.format("%d", x, grouping=True) '1,234,567' >>> locale.format("%s%.*f", (conv['currency_symbol'], ... conv['frac_digits'], x), grouping=True) '$1,234,567.80'
The string module includes a versatile Template class with a simplified syntax suitable for editing by end-users. This allows users to customize their applications without having to alter the application.
The format uses placeholder names formed by "$" with valid Python identifiers (alphanumeric characters and underscores). Surrounding the placeholder with braces allows it to be followed by more alphanumeric letters with no intervening spaces. Writing "$$" creates a single escaped "$":
>>> from string import Template >>> t = Template('${village}folk send $$10 to $cause.') >>> t.substitute(village='Nottingham', cause='the ditch fund') 'Nottinghamfolk send $10 to the ditch fund.'
The substitute method raises a KeyError when a placeholder is not supplied in a dictionary or a keyword argument. For mail-merge style applications, user supplied data may be incomplete and the safe_substitute method may be more appropriate -- it will leave placeholders unchanged if data is missing:
>>> t = Template('Return the $item to $owner.') >>> d = dict(item='unladen swallow') >>> t.substitute(d) Traceback (most recent call last): . . . KeyError: 'owner' >>> t.safe_substitute(d) 'Return the unladen swallow to $owner.'
Template subclasses can specify a custom delimiter. For example, a batch renaming utility for a photo browser may elect to use percent signs for placeholders such as the current date, image sequence number, or file format:
>>> import time, os.path >>> photofiles = ['img_1074.jpg', 'img_1076.jpg', 'img_1077.jpg'] >>> class BatchRename(Template): ... delimiter = '%' >>> fmt = raw_input('Enter rename style (%d-date %n-seqnum %f-format): ') Enter rename style (%d-date %n-seqnum %f-format): Ashley_%n%f >>> t = BatchRename(fmt) >>> date = time.strftime('%d%b%y') >>> for i, filename in enumerate(photofiles): ... base, ext = os.path.splitext(filename) ... newname = t.substitute(d=date, n=i, f=ext) ... print '%s --> %s' % (filename, newname) img_1074.jpg --> Ashley_0.jpg img_1076.jpg --> Ashley_1.jpg img_1077.jpg --> Ashley_2.jpg
Another application for templating is separating program logic from the details of multiple output formats. This makes it possible to substitute custom templates for XML files, plain text reports, and HTML web reports.
The
struct
module provides pack() and unpack() functions for working with variable length binary record formats. The following example shows how to loop through header information in a ZIP file (with pack codes "H"
and "L"
representing two and four byte unsigned numbers respectively):
import struct data = open('myfile.zip', 'rb').read() start = 0 for i in range(3): # show the first 3 file headers start += 14 fields = struct.unpack('LLLHH', data[start:start+16]) crc32, comp_size, uncomp_size, filenamesize, extra_size = fields start += 16 filename = data[start:start+filenamesize] start += filenamesize extra = data[start:start+extra_size] print filename, hex(crc32), comp_size, uncomp_size start += extra_size + comp_size # skip to the next header
Threading is a technique for decoupling tasks which are not sequentially dependent. Threads can be used to improve the responsiveness of applications that accept user input while other tasks run in the background. A related use case is running I/O in parallel with computations in another thread.
The following code shows how the high level threading module can run tasks in background while the main program continues to run:
import threading, zipfile class AsyncZip(threading.Thread): def __init__(self, infile, outfile): threading.Thread.__init__(self) self.infile = infile self.outfile = outfile def run(self): f = zipfile.ZipFile(self.outfile, 'w', zipfile.ZIP_DEFLATED) f.write(self.infile) f.close() print 'Finished background zip of: ', self.infile background = AsyncZip('mydata.txt', 'myarchive.zip') background.start() print 'The main program continues to run in foreground.' background.join() # Wait for the background task to finish print 'Main program waited until background was done.'
The principal challenge of multi-threaded applications is coordinating threads that share data or other resources. To that end, the threading module provides a number of synchronization primitives including locks, events, condition variables, and semaphores.
While those tools are powerful, minor design errors can result in problems that are difficult to reproduce. So, the preferred approach to task coordination is to concentrate all access to a resource in a single thread and then use the Queue module to feed that thread with requests from other threads. Applications using Queue objects for inter-thread communication and coordination are easier to design, more readable, and more reliable.
The
logging
module offers a full featured and flexible logging system. At its simplest, log messages are sent to a file or to sys.stderr
:
import logging logging.debug('Debugging information') logging.info('Informational message') logging.warning('Warning:config file %s not found', 'server.conf') logging.error('Error occurred') logging.critical('Critical error -- shutting down')
This produces the following output:
WARNING:root:Warning:config file server.conf not found ERROR:root:Error occurred CRITICAL:root:Critical error -- shutting down
By default, informational and debugging messages are suppressed and the output is sent to standard error. Other output options include routing messages through email, datagrams, sockets, or to an HTTP Server. New filters can select different routing based on message priority: DEBUG, INFO, WARNING, ERROR, and CRITICAL.
The logging system can be configured directly from Python or can be loaded from a user editable configuration file for customized logging without altering the application.
Python does automatic memory management (reference counting for most objects and garbage collection to eliminate cycles). The memory is freed shortly after the last reference to it has been eliminated.
This approach works fine for most applications but occasionally there is a need to track objects only as long as they are being used by something else. Unfortunately, just tracking them creates a reference that makes them permanent. The weakref module provides tools for tracking objects without creating a reference. When the object is no longer needed, it is automatically removed from a weakref table and a callback is triggered for weakref objects. Typical applications include caching objects that are expensive to create:
>>> import weakref, gc >>> class A: ... def __init__(self, value): ... self.value = value ... def __repr__(self): ... return str(self.value) ... >>> a = A(10) # create a reference >>> d = weakref.WeakValueDictionary() >>> d['primary'] = a # does not create a reference >>> d['primary'] # fetch the object if it is still alive 10 >>> del a # remove the one reference >>> gc.collect() # run garbage collection right away 0 >>> d['primary'] # entry was automatically removed Traceback (most recent call last): File "<pyshell#108>", line 1, in -toplevel- d['primary'] # entry was automatically removed File "C:/PY24/lib/weakref.py", line 46, in __getitem__ o = self.data[key]() KeyError: 'primary'
Many data structure needs can be met with the built-in list type. However, sometimes there is a need for alternative implementations with different performance trade-offs.
The
array
module provides an array() object that is like a list that stores only homogenous data but stores it more compactly. The following example shows an array of numbers stored as two byte unsigned binary numbers (typecode "H"
) rather than the usual 16 bytes per entry for regular lists of python int objects:
>>> from array import array >>> a = array('H', [4000, 10, 700, 22222]) >>> sum(a) 26932 >>> a[1:3] array('H', [10, 700])
The collections module provides a deque() object that is like a list with faster appends and pops from the left side but slower lookups in the middle. These objects are well suited for implementing queues and breadth first tree searches:
>>> from collections import deque >>> d = deque(["task1", "task2", "task3"]) >>> d.append("task4") >>> print "Handling", d.popleft() Handling task1 unsearched = deque([starting_node]) def breadth_first_search(unsearched): node = unsearched.popleft() for m in gen_moves(node): if is_goal(m): return m unsearched.append(m)
In addition to alternative list implementations, the library also offers other tools such as the bisect module with functions for manipulating sorted lists:
>>> import bisect >>> scores = [(100, 'perl'), (200, 'tcl'), (400, 'lua'), (500, 'python')] >>> bisect.insort(scores, (300, 'ruby')) >>> scores [(100, 'perl'), (200, 'tcl'), (300, 'ruby'), (400, 'lua'), (500, 'python')]
The heapq module provides functions for implementing heaps based on regular lists. The lowest valued entry is always kept at position zero. This is useful for applications which repeatedly access the smallest element but do not want to run a full list sort:
>>> from heapq import heapify, heappop, heappush >>> data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0] >>> heapify(data) # rearrange the list into heap order >>> heappush(data, -5) # add a new entry >>> [heappop(data) for i in range(3)] # fetch the three smallest entries [-5, 0, 1]
The decimal module offers a Decimal datatype for decimal floating point arithmetic. Compared to the built-in float implementation of binary floating point, the new class is especially helpful for financial applications and other uses which require exact decimal representation, control over precision, control over rounding to meet legal or regulatory requirements, tracking of significant decimal places, or for applications where the user expects the results to match calculations done by hand.
For example, calculating a 5% tax on a 70 cent phone charge gives different results in decimal floating point and binary floating point. The difference becomes significant if the results are rounded to the nearest cent:
>>> from decimal import * >>> Decimal('0.70') * Decimal('1.05') Decimal("0.7350") >>> .70 * 1.05 0.73499999999999999
The Decimal result keeps a trailing zero, automatically inferring four place significance from multiplicands with two place significance. Decimal reproduces mathematics as done by hand and avoids issues that can arise when binary floating point cannot exactly represent decimal quantities.
Exact representation enables the Decimal class to perform modulo calculations and equality tests that are unsuitable for binary floating point:
>>> Decimal('1.00') % Decimal('.10') Decimal("0.00") >>> 1.00 % 0.10 0.09999999999999995 >>> sum([Decimal('0.1')]*10) == Decimal('1.0') True >>> sum([0.1]*10) == 1.0 False
The decimal module provides arithmetic with as much precision as needed:
>>> getcontext().prec = 36 >>> Decimal(1) / Decimal(7) Decimal("0.142857142857142857142857142857142857")
The os module provides dozens of functions for interacting with the operating system:
>>> import os >>> os.system('time 0:02') 0 >>> os.getcwd() # Return the current working directory 'C:\\Python24' >>> os.chdir('/server/accesslogs')
Be sure to use the "import os" style instead of "from os import *". This will keep os.open() from shadowing the builtin open() function which operates much differently.
The builtin dir() and help() functions are useful as interactive aids for working with large modules like os:
>>> import os >>> dir(os) <returns a list of all module functions> >>> help(os) <returns an extensive manual page created from the module's docstrings>
For daily file and directory management tasks, the shutil module provides a higher level interface that is easier to use:
>>> import shutil >>> shutil.copyfile('data.db', 'archive.db') >>> shutil.move('/build/executables', 'installdir')
The glob module provides a function for making file lists from directory wildcard searches:
>>> import glob >>> glob.glob('*.py') ['primes.py', 'random.py', 'quote.py']
Common utility scripts often need to process command line arguments. These arguments are stored in the sys module's argv attribute as a list. For instance the following output results from running "python demo.py one two three" at the command line:
>>> import sys >>> print sys.argv ['demo.py', 'one', 'two', 'three']
The getopt module processes sys.argv using the conventions of the Unixgetopt() function. More powerful and flexible command line processing is provided by the optparse module.
The sys module also has attributes for stdin, stdout, and stderr. The latter is useful for emitting warnings and error messages to make them visible even when stdout has been redirected:
>>> sys.stderr.write('Warning, log file not found starting a new one\n') Warning, log file not found starting a new one
The most direct way to terminate a script is to use "sys.exit()".
The re module provides regular expression tools for advanced string processing. For complex matching and manipulation, regular expressions offer succinct, optimized solutions:
>>> import re >>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest') ['foot', 'fell', 'fastest'] >>> re.sub(r'(\b[a-z]+) \1', r'\1', 'cat in the the hat') 'cat in the hat'
When only simple capabilities are needed, string methods are preferred because they are easier to read and debug:
>>> 'tea for too'.replace('too', 'two') 'tea for two'
The math module gives access to the underlying C library functions for floating point math:
>>> import math >>> math.cos(math.pi / 4.0) 0.70710678118654757 >>> math.log(1024, 2) 10.0
The random module provides tools for making random selections:
>>> import random >>> random.choice(['apple', 'pear', 'banana']) 'apple' >>> random.sample(xrange(100), 10) # sampling without replacement [30, 83, 16, 4, 8, 81, 41, 50, 18, 33] >>> random.random() # random float 0.17970987693706186 >>> random.randrange(6) # random integer chosen from range(6) 4
There are a number of modules for accessing the internet and processing internet protocols. Two of the simplest are urllib2 for retrieving data from urls and smtplib for sending mail:
>>> import urllib2 >>> for line in urllib2.urlopen('http://tycho.usno.navy.mil/cgi-bin/timer.pl'): ... if 'EST' in line: # look for Eastern Standard Time ... print line <BR>Nov. 25, 09:43:32 PM EST >>> import smtplib >>> server = smtplib.SMTP('localhost') >>> server.sendmail('soothsayer@example.org', 'jcaesar@example.org', """To: jcaesar@example.org From: soothsayer@example.org Beware the Ides of March. """) >>> server.quit()
The datetime module supplies classes for manipulating dates and times in both simple and complex ways. While date and time arithmetic is supported, the focus of the implementation is on efficient member extraction for output formatting and manipulation. The module also supports objects that are time zone aware.
# dates are easily constructed and formatted >>> from datetime import date >>> now = date.today() >>> now datetime.date(2003, 12, 2) >>> now.strftime("%m-%d-%y. %d %b %Y is a %A on the %d day of %B.") '12-02-03. 02 Dec 2003 is a Tuesday on the 02 day of December.' # dates support calendar arithmetic >>> birthday = date(1964, 7, 31) >>> age = now - birthday >>> age.days 14368
Common data archiving and compression formats are directly supported by modules including: zlib, gzip, bz2, zipfile, and tarfile.
>>> import zlib >>> s = 'witch which has which witches wrist watch' >>> len(s) 41 >>> t = zlib.compress(s) >>> len(t) 37 >>> zlib.decompress(t) 'witch which has which witches wrist watch' >>> zlib.crc32(s) 226805979
Some Python users develop a deep interest in knowing the relative performance of different approaches to the same problem. Python provides a measurement tool that answers those questions immediately.
For example, it may be tempting to use the tuple packing and unpacking feature instead of the traditional approach to swapping arguments. The timeit module quickly demonstrates a modest performance advantage:
>>> from timeit import Timer >>> Timer('t=a; a=b; b=t', 'a=1; b=2').timeit() 0.57535828626024577 >>> Timer('a,b = b,a', 'a=1; b=2').timeit() 0.54962537085770791
In contrast to timeit's fine level of granularity, the profile and pstats modules provide tools for identifying time critical sections in larger blocks of code.
One approach for developing high quality software is to write tests for each function as it is developed and to run those tests frequently during the development process.
The doctest module provides a tool for scanning a module and validating tests embedded in a program's docstrings. Test construction is as simple as cutting-and-pasting a typical call along with its results into the docstring. This improves the documentation by providing the user with an example and it allows the doctest module to make sure the code remains true to the documentation:
def average(values): """Computes the arithmetic mean of a list of numbers. >>> print average([20, 30, 70]) 40.0 """ return sum(values, 0.0) / len(values) import doctest doctest.testmod() # automatically validate the embedded tests
The unittest module is not as effortless as the doctest module, but it allows a more comprehensive set of tests to be maintained in a separate file:
import unittest class TestStatisticalFunctions(unittest.TestCase): def test_average(self): self.assertEqual(average([20, 30, 70]), 40.0) self.assertEqual(round(average([1, 5, 7]), 1), 4.3) self.assertRaises(ZeroDivisionError, average, []) self.assertRaises(TypeError, average, 20, 30, 70) unittest.main() # Calling from the command line invokes all tests
Python has a ``batteries included'' philosophy. This is best seen through the sophisticated and robust capabilities of its larger packages. For example:
Note Two :about Tuples (distinguish between string type and tuples tpye,especially zero or only one items contained in a tuples )
A special problem is the construction of tuples containing 0 or 1 items: the syntax has some extra quirks to accommodate these. Empty tuples are constructed by an empty pair of parentheses; a tuple with one item is constructed by following a value with a comma (it is not sufficient to enclose a single value in parentheses). Ugly, but effective. For example:
>>> empty = ()
>>> singleton = 'hello', # <-- note trailing comma
>>> len(empty)
0
>>> len(singleton)
1
>>> singleton
('hello',)
but if you write a statement like this :
>>> singleton = 'hello' # it means that you define or construct a string type,not a tuples
>>> singleton
'hello'
It is possible to nest lists (create lists containing other lists), for example:
>>> q = [2, 3]
>>> p = [1, q, 4]
>>> len(p)
3
>>> p[1]
[2, 3]
>>> p[1][0]
2
>>> p[1].append('xtra')
>>> p
[1, [2, 3, 'xtra'], 4]
>>> q
[2, 3, 'xtra']
Note Two : about for statement
It is not safe to modify the sequence being iterated over in the loop (this can only happen for mutable sequence types, such as lists). If you need to modify the list you are iterating over (for example, to duplicate selected items) you must iterate over a copy. The slice notation makes this particularly convenient:
valid statements: it will work normally
>>> for x in a[:]: # make a slice copy of the entire list
... if len(x) > 6:
... a.insert(0, x)
...
>>> a
['defenestrate', 'cat', 'window', 'defenestrate']
invalid statement: you prompt will die
>>> for x in a : # make a slice copy of the entire list
... if len(x) > 6:
... a.insert(0, x)
...
Note that: in the first statement the first row ,the for statement ues 'a[:] ' ,it means that to make a slice of it;but in the second statement,the for statement ues 'a' directly ,so cause a bad result
Note Three: Compare for efficiency
str_test = []
# method one :
str_test.append('attach')
#method two:
str_test = str_test + ['attach']
The Two method above has the same function ,but the more efficient one is the first one
Note Four :about Defining Functions
Form 1:Default Argument Values
The default value is evaluated only once.
def f(a, L=[]):
L.append(a)
return L
print f(1)
print f(2)
print f(3)
This will print
[1] [1, 2] [1, 2, 3]
If you don't want the default to be shared between subsequent calls, you can write the function like this instead:
def f(a, L=None): if L is None: L = [] L.append(a) return L
Form 2 : Keyword ArgumentsWhen a final formal parameter of the form **name is present, it receives a dictionary containing all keyword arguments except
for those corresponding to a formal parameter. This may be combined with a formal parameter of the form *name (described in
the next subsection) which receives a tuple containing the positional arguments beyond the formal parameter list. (*name must
occur before **name) For example, if we define a function like this: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]It could be called like this:
cheeseshop('Limburger', "It's very runny, sir.", "It's really very, VERY runny, sir.", client='John Cleese', shopkeeper='Michael Palin', sketch='Cheese Shop Sketch')and of course it would print:
-- 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 SketchNote that the sort() method of the list of keyword argument names is called before printing the contents of the keywords
dictionary; if this is not done, the order in which the arguments are printed is undefined.
-1
is actually an expression composed of the unary operator `-
' and the literal 1<>
and !=
are alternate spellings of the same operator. !=
is the preferred spelling; <>
is obsolescent. _
. This means that when you are using Python as a desk calculator, it is somewhat easier to continue calculations, for example:
1. Reason One : 长整型无长度限制Q除?jin)?sh)脑硬件的限制
Although both lower case "l" and upper case "L" are allowed as suffix for long integers, it is strongly recommended to always use "L", since the letter "l" looks too much like the digit "1".
Plain integer literals that are above the largest representable plain integer (e.g., 2147483647 when using 32-bit arithmetic) are accepted as if they were long integers instead.
There is no limit for long integer literals apart from what can be stored in available memory.
Some examples of plain integer literals (first row) and long integer literals (second and third rows):
7 2147483647 0177
3L 79228162514264337593543950336L 0377L 0x100000000L
79228162514264337593543950336 0xdeadbeef
2. Reason Two : (quote)
一个pythontipQ交换两个变量的|而且不用第三个变量Q?
>>> a,b = 1,2
>>> a,b = b,a
>>> a,b
(2, 1)
>>>
3.Reason Three:
它是用C语言开发的Q但是效率比起C语言也差?jin)多,当然没C快啦Q但是他里面的很多函数非常方便,功能比C强大很多?br />4.Reason Four :
最让h兴奋的原因就是BitComet是它开发出来的?br />
他避免了(jin)很多初学E序设计时常常出现的问题Q尽对于大多数人来说都是几乎不?x)发生的Q但是从q点可以看出它对它的用户是傻瓜开始的。因为傻瓜才?x)犯哪些错误Q?br />