Changeset 929

Show
Ignore:
Timestamp:
Mon Mar 20 13:15:15 2006
Author:
osmond
Message:

update

Files:

Legend:

Unmodified
Added
Removed
Modified
  • zh-translations/branches/diveintopython-zh-5.4/zh-cn/xml/fileinfo.xml

    r858 r929  
    72 72 <calloutlist>  
    73 73 <callout arearefs="fileinfo_divein.1.1">  
    74   <para>这个程序的输入要依赖于你硬盘上的文件。为了得到有意义的输出,你应该修改目录路径指向你自已机器上的一个MP3文件目录。</para>  
      74 <para>这个程序的输入要取决于你硬盘上的文件。为了得到有意义的输出,你应该修改目录路径指向你自已机器上的一个MP3文件目录。</para>  
    74 74 </callout>  
    75 75 </calloutlist>  
     
    343 343 <note id="compare.new.java" role="compare" vendor="java">  
    344 344 <title>&python; &vs; &java;: 类的实例化</title>  
    345   <para>在 &python; 中,创建类的实例只要调用一个类,仿佛它是一个函数就行了。不象 &cpp; 或 &java; 有一个��式的 &new; 操作符。</para>  
      345 <para>在 &python; 中,创建类的实例只要调用一个类,仿佛它是一个函数就行了。不象 &cpp; 或 &java; 有一个��确的 &new; 操作符。</para>  
    345 345 </note>  
    346 346 <section>  
    347 347 <title>垃圾回收</title>  
    348   <para>如果如创建一个新的实例是容易的,那么销毁它们甚至更容易。通常,不需要显式地释放实例,因为当指派给它们的变量超出作用域时,它们会被自动地释放。内存泄漏在 &python; 中很少见。</para>  
      348 <para>如果说创建一个新的实例是容易的,那么销毁它们甚至更容易。通常,不需要明确地释放实例,因为当指派给它们的变量超出作用域时,它们会被自动地释放。内存泄漏在 &python; 中很少见。</para>  
    348 348 <example id="fileinfo.scope">  
    349 349 <title>尝试实现内存泄漏</title>  
     
    364 364 </calloutlist>  
    365 365 </example>  
    366   <para>对于这种垃圾收集的方式,技术上的术语叫做<quote>引用计数</quote>。&python; 维护着对每个实例的引用列表。在上面的例子中,���于 &fileinfo_classname; 实例只有一个引用:局部变量 <varname>f</varname>。当函数结束时,变量 <varname>f</varname> 超出作用域,所以引用计数降为 &zero;,则 &python; 自动销毁掉实例。</para>  
      366 <para>对于这种垃圾收集的方式,技术上的术语叫做<quote>引用计数</quote>。&python; 维护着对每个实例的引用列表。在上面的例子中,���有一个 &fileinfo_classname; 的实例引用:局部变量 <varname>f</varname>。当函数结束时,变量 <varname>f</varname> 超出作用域,所以引用计数降为 &zero;,则 &python; 自动销毁掉实例。</para>  
    366 366 <para>在 &python; 的以前版本中,存在引用计数失败的情况,这样 &python; 不能在后面进行清除。如果你创建两个实例,它们相互引用(例如,双重链表,每一个结点有都一个指向列表中前一个和后一个结点的指针),任一个实例都不会被自动销毁,因为 &python; (正确)认为对于每个实例都存在一个引用。 &python; 2.0有一种额外的垃圾回收方式,叫做<quote>标记后清除</quote>,它足够聪明,可以正确地清除循环引用。</para>  
    367   <para>作为以前主修哲学专业的人来说,让我感到困惑的是,思索当没有人对事物进行观察时,它们就消失了,但是这确实是在 &python; 中所发生的。通常,你可以完全忘记内存管理,让 &python; 在后面进行清理。</para>  
      367 <para>作为曾经读过哲学专业的一员,让我感到困惑的是,当没有人对事物进行观察时,它们就消失了,但是这确实是在 &python; 中所发生的。通常,你可以完全忘记内存管理,让 &python; 在后面进行清理。</para>  
    367 367 <itemizedlist role="furtherreading">  
    368 368 <title>进一步阅读关于垃圾回收</title>  
     
    379 379 <abstract>  
    380 380 <title/>  
    381   <para>如你所见, &fileinfo_classname; 是一个象字典一样动作的类。为了进一步揭示这一点,让我们看一看在 &userdict; 模块中的 &userdict_classname; 类,它是我们的 &fileinfo_classname; 类的父类。没有什么特别的,类是用 &python; 写的,并且保存在一个 <literal>.py</literal> 文件里,就象我们的代码。特别的,它保存在你的 &python; 安装目录的  <filename class="directory">lib</filename>  目录下。</para>  
      381 <para>如你所见, &fileinfo_classname; 是一个象字典一样动作的类。为了进一步揭示这一点,让我们看一看在 &userdict; 模块中的 &userdict_classname; 类,它是我们的 &fileinfo_classname; 类的父类。它没有什么特别的,也是用 &python; 写的,并且保存在一个 <literal>.py</literal> 文件里,就象我们其他的代码。特别之处在于,它保存在你的 &python; 安装目录的  <filename class="directory">lib</filename>  目录下。</para>  
    381 381 </abstract>  
    382 382 <tip id="tip.locate">  
     
    451 451 <calloutlist>  
    452 452 <callout arearefs="fileinfo.userdict.2.1">  
    453   <para>&clear; 是一个普通的类方法,可以在任何时候被任何人公开调用。注意,&clear; 象所有的类方法一样(常规的或专用的),使用  &self;  作为它的第一个参数。(记住,当你调用方法时,不用包括 &self;;这件事是 &python; 替你做的。) 还应注意这个封装类的基本技术:将一个真正的字典 (<varname>data</varname>)  作为数据属性保存起来,定义所有真正字典���拥有的方法,并且将每个类方法重定向到真正字典上的相应方法。(一旦你已经忘记了,字典的 &clear; 方法 <link linkend="odbchelper.dict.del">删除它的所有关键字</link> 和关键字相应的值。)</para>  
      453 <para>&clear; 是一个普通的类方法,可以在任何时候被任何人公开调用。注意,&clear; 象所有的类方法一样(常规的或专用的),使用  &self;  作为它的第一个参数。(记住,当你调用方法时,不用包括 &self;;这件事是 &python; 替你做的。) 还应注意这个封装类的基本技术:将一个真正的字典 (<varname>data</varname>)  作为数据属性保存起来,定义所有真正字典���拥有的方法,并且将每个类方法重定向到真正字典上的相应方法。(在你忘记的情况下,字典的 &clear; 方法 <link linkend="odbchelper.dict.del">删除它的所有关键字</link> 和关键字相应的值。)</para>  
    453 453 </callout>  
    454 454 <callout arearefs="fileinfo.userdict.2.2">  
     
    501 501 <para>除了普通的类方法,还有一些对于 &python; 类可以定义的专用方法。专用方法是在特殊情况下或当使用特别语法时由 &python; 替你调用的,而不是在代码中直接调用(象普通的方法那样)。</para>  
    502 502 </abstract>  
    503   <para>就象你在 <link linkend="fileinfo.userdict">上一节</link> 所看到的,普通的方法对在类中封装字典很有帮助。但是只有普通方法是不够的,因为除了对字典调用方法之外,还有很多事情可以做的。例如,你可以通过一种没有包括��式方法调用的语法来 <link linkend="odbchelper.dict.define">获得</link> 和 <link linkend="odbchelper.dict.modify">设置</link> 数据项。这就是专用方法产生的原因:它们提供了一种方法,可以将非方法调用语法映射到方法调用上。</para>  
      503 <para>就象你在 <link linkend="fileinfo.userdict">上一节</link> 所看到的,普通的方法对在类中封装字典很有帮助。但是只有普通方法是不够的,因为除了对字典调用方法之外,还有很多事情可以做的。例如,你可以通过一种没有包括��确方法调用的语法来 <link linkend="odbchelper.dict.define">获得</link> 和 <link linkend="odbchelper.dict.modify">设置</link> 数据项。这就是专用方法产生的原因:它们提供了一种方法,可以将非方法调用语法映射到方法调用上。</para>  
    503 503 <section>  
    504 504 <title>获得和设置数据项</title>  
     
    594 594 <calloutlist>  
    595 595 <callout arearefs="fileinfo.specialmethods.4.1">  
    596   <para>首先,我们创建了一个 &mp3fileinfo_classname; 的实例,没有传递给它文件名。(我们可以不用它,因为 &init; 方法的 <varname>filename</varname> 参数是 <link linkend="apihelper.optional">可选的</link>。) 因为 &mp3fileinfo_classname; 没有它自已的 &init; 方法,&python; 沿着父类树走,发现了 &fileinfo_classname; 的 &init; 方法。这个 &init; 方法手工调用了 &userdict_classname; 的 &init; 方法,然后设置 <literal>name</literal> 关键字为 <varname>filename</varname>,它为 &none;,因为我们还没有传入一个文件名。所以,<varname>mp3file</varname> 最初看上去象���一个关键字, <literal>name</literal>,它的值为 &none; 的字典。</para>  
      596 <para>首先,我们创建了一个 &mp3fileinfo_classname; 的实例,没有传递给它文件名。(我们可以不用它,因为 &init; 方法的 <varname>filename</varname> 参数是 <link linkend="apihelper.optional">可选的</link>。) 因为 &mp3fileinfo_classname; 没有它自已的 &init; 方法,&python; 沿着父类树走,发现了 &fileinfo_classname; 的 &init; 方法。这个 &init; 方法手工调用了 &userdict_classname; 的 &init; 方法,然后设置 <literal>name</literal> 关键字为 <varname>filename</varname>,它为 &none;,因为我们还没有传入一个文件名。所以,<varname>mp3file</varname> 最初看上去象���有一个关键字,值为 &none; 的<literal>name</literal>,的字典。</para>  
    596 596 </callout>  
    597 597 <callout arearefs="fileinfo.specialmethods.4.2">  
     
    642 642 <note id="compare.strequals.java" role="compare" vendor="java">  
    643 643 <title>&python; &vs; &java; equality and identity</title>  
    644   <para>在 &java; 中,通过使用 <literal>str1 == str2</literal> 可以决定两个字符串变量是否指向同一块物理内存位置。这就做 <emphasis>对象同一性</emphasis>,在 &python; 中写为 <literal>str1 is str2</literal>。在 &java; 中为了比较两个字符串值,你要使用 <literal>str1.equals(str2)</literal>;在 &python; 中,你要使用 <literal>str1 == str2</literal>。 某些 &java; 程序员,他们已经被教授得认为,因为在 &java; 中 &comparisonequals; 是通过一致性而不是值来进行比较的,所以 &java; 是更好的地方。这些人要转到 &python; 上来可能要花些时间。在 &java; 中,你通过 <literal>str1 == str2</literal> 来半段两个字符串是否指向同一物理内存位置。这被称作 <emphasis>对象确定(object identity)</emphasis>, 在 &python; 中被写作 <literal>str1 is str2</literal>。 在 &java; 中比较字符串使用 <literal>str1.equals(str2)</literal> ,而在 &python; 中,你使用 <literal>str1 == str2</literal>。那些素来认为 &java; 中比较对象身份而不是值的 &comparisonequals; 令世界变得更好的 &java; 程序员可能对 &python; 中的<quote>这个缺少</quote>接起来有困难。</para>  
      644 <para>在 &java; 中,通过使用 <literal>str1 == str2</literal> 可以决定两个字符串变量是否指向同一块物理内存位置。这就做 <emphasis>对象同一性</emphasis>,在 &python; 中写为 <literal>str1 is str2</literal>。在 &java; 中为了比较两个字符串值,你要使用 <literal>str1.equals(str2)</literal>;在 &python; 中,你要使用 <literal>str1 == str2</literal>。 某些 &java; 程序员,他们已经被教授得认为,因为在 &java; 中 &comparisonequals; 是通过一致性而不是值来进行比较的,所以 &java; 是更好的地方。这些人要转到 &python; 上来可能要花些时间。在 &java; 中,你通过 <literal>str1 == str2</literal> 来半段两个字符串是否指向同一物理内存位置。这被称作 <emphasis>对象确定(object identity)</emphasis>, 在 &python; 中被写作 <literal>str1 is str2</literal>。 在 &java; 中比较字符串使用 <literal>str1.equals(str2)</literal> ,而在 &python; 中,你使用 <literal>str1 == str2</literal>。那些素来认为 &java; 中比较对象身份而不是值的 &comparisonequals; 令世界变得更好的 &java; 程序员可能对 &python; 中的<quote>这个缺少</quote>接起来有困难。</para>  
    644 644 </note>  
    645   <para>在这个地方,你可能会想,<quote>所有这些工作只是为了在类中做一些我可以对一个内置数据类型所做的操作</quote>。不错,如果你能够从象字典一样的内置数据类型进行继承的话,事情就容易多了(那样整个 &userdict_classname; 类将完全不需要了)。但是也许你可以,专用方法仍然是有用的,因为它们可以用于任何的类,而不只是象 &userdict_classname; 的封装类。</para>  
      645 <para>在这个地方,你可能会想,<quote>所有这些工作只是为了在类中做一些我可以对一个内置数据类型所做的操作</quote>。不错,如果你能够从象字典一样的内置数据类型进行继承的话,事情就容易多了(那样整个 &userdict_classname; 类将完全不需要了)。尽管你可以这样做,专用方法仍然是有用的,因为它们可以用于任何的类,而不只是象 &userdict_classname; 这样的封装类。</para>  
    645 645 <para>专用方法意味着 <emphasis>任何类</emphasis> 可以象字典一样保存键-值对,只要定义  &setitem; 方法。任何类可以表现得象一个序列,只要通过定义 &getitem; 方法。任何定义了 &cmpspecial; 方法的类可以用 &comparisonequals; 进行比较。并且如果你的类表现拥有类似长度的东西,不要定义 <function>GetLength</function> 方法,而定义 &lenspecial; 方法,使用 <literal>len(<replaceable>instance</replaceable>)</literal>。</para>  
    646 646 <note id="note.physical.v.logical">  
     
    838 838 <listitem><para><link linkend="odbchelper.stringformatting.coerce">未强制转换就混和数据类型</link> 将引发 <errorcode>TypeError</errorcode> 异常。</para></listitem>  
    839 839 </itemizedlist>  
    840   <para>在这些情况下,我们都在简单使用 &python; &ide;:一个错误发生了,异常被打印出来 (根据你的 &ide;,有意地以一种刺眼的红色形式表示),并且就这些。这叫做 <emphasis>未处理</emphasis> 异常;当异常被引发时,没有代码来显式地关注它和处理它,所以异常被传给置在 &python; 中的缺省的处理,它会输出一些调试信息并且终止运行。在 &ide; 中,这不是什么大事,但是如果发生在你真正的 &python; 程序运行的时候,整个程序将会终止。</para>  
      840 <para>在这些情况下,我们都在简单使用 &python; &ide;:一个错误发生了,异常被打印出来 (根据你的 &ide;,有意地以一种刺眼的红色形式表示),这便是。这叫做 <emphasis>未处理</emphasis> 异常;当异常被引发时,没有代码来明确地关注和处理它,所以异常被传给置在 &python; 中的缺省的处理,它会输出一些调试信息并且终止运行。在 &ide; 中,这不是什么大事,但是如果发生在你真正的 &python; 程序运行的时候,整个程序将会终止。</para>  
    840 840 <para>然而,一个异常不一定会引起程序的完全崩溃。当异常引发时,可以被  <emphasis>处理</emphasis> 掉。有时候一个异常实际是因为代码中的 bug (比如使用一个不存在的变量),但是许多时候,一个异常是可以预计的。如果你打开一个文件,它可能不存在。如果你连接一个数据库,它可能不可连接或没有访问所需的正确的安全证书。如果知道一行代码可能会引发异常,你应该使用一个 &tryexcept; 块来处理异常。</para>  
    841 841 <example>  
    867 867 </calloutlist>  
    868 868 </example>  
    869   <para>异常可能看上去不友好 (毕竟,如果你不捕捉异常,整个程序将崩溃),但是考虑一下别的方法。你���愿找回对于不存在文件的不可用的文件对象吗?不管怎么样你都得检查它的有效性,而且如果你忘记了,你的程序将会在下面某个地方给出奇怪的错误,这样你将不得不追溯到源程序。我确信你做过这种事;这可并不有趣。使用异常,一发生错误,你就可以在问题的源头通过标准的方法来处理它们。</para>  
      869 <para>异常可能看上去不友好 (毕竟,如果你不捕捉异常,整个程序将崩溃),但是考虑一下别的方法。你���望获得一个没有用的文件对象而不是一个不存在的文件吧?不管怎么样你都得检查它的有效性,而且如果你忘记了,你的程序将会在下面某个地方给出奇怪的错误,这样你将不得不追溯到源程序。我确信你做过这种事;这可并不有趣。使用异常,一发生错误,你就可以在问题的源头通过标准的方法来处理它们。</para>  
    869 869 <section>  
    870 870 <title>为其他用途使用异常</title>