Changeset 919
- Timestamp:
- Sun Mar 19 00:36:17 2006
- Files:
Legend:
- Unmodified
- Added
- Removed
- Modified
-
zh-translations/branches/diveintopython-zh-5.4/zh-cn/xml/plural.xml
r918 r919 19 19 <listitem><para>如果一切规则都不适用,就只添加 S 并祈祷不会错。</para></listitem> 20 20 </orderedlist> 21 <para>(我知道有很多例外情况, 比如: <quote>Man</quote> 变成 <quote>men</quote>, <quote>woman</quote> 变成 <quote>women</quote>,但是, <quote>human</quote> 却变成 <quote>humans</quote>。 <quote>Mouse</quote> 变成 <quote>mice</quote>, <quote>louse</quote> 变成 <quote>lice</quote>, 但是, <quote>house</quote> 却变成 <quote>houses</quote>。 <quote>Knife</quote> 变成 <quote>knives</quote>, <quote>wife</quote> 变成 <quote>wives</quote>,但是 <quote>lowlife</quote> 却变成 <quote>lowlifes</quote>。 更不要说那些复数 不需要变化的词了,比如 <quote>sheep</quote>, <quote>deer</quote>, and<quote>haiku</quote>。)</para>21 <para>(我知道有很多例外情况, 比如: <quote>Man</quote> 变成 <quote>men</quote>, <quote>woman</quote> 变成 <quote>women</quote>,但是, <quote>human</quote> 却变成 <quote>humans</quote>。 <quote>Mouse</quote> 变成 <quote>mice</quote>, <quote>louse</quote> 变成 <quote>lice</quote>, 但是, <quote>house</quote> 却变成 <quote>houses</quote>。 <quote>Knife</quote> 变成 <quote>knives</quote>, <quote>wife</quote> 变成 <quote>wives</quote>,但是 <quote>lowlife</quote> 却变成 <quote>lowlifes</quote>。 更不要说那些复数根本就不需要变化的词了,比如 <quote>sheep</quote>, <quote>deer</quote> 和 <quote>haiku</quote>。)</para> 21 21 <para>其他的语言当然完全不同。</para> 22 22 <para>让我们来设计一个复数化名词的模块吧! 从英语名词开始,仅考虑上面的四种规则,但是记得你将来需要不断添加规则,更可能最后添加进更多的语言。</para> … … 72 72 </callout> 73 73 <callout arearefs="plural.stage1.2.2"> 74 <para>好的,现在找出 <literal>a</literal>, <literal>b</literal>,或者 <literal>c</literal>并以 <literal>o</literal> 取代之。 <literal>Mark</literal> 就变成 <literal>Mork</literal> 了。</para> 74 <para>好的,现在找出 <literal>a</literal>, <literal>b</literal>,或者 <literal>c</literal> 并以 <literal>o</literal> 取代之。 <literal>Mark</literal> 就变成 <literal>Mork</literal> 了。</para> 74 74 </callout> 75 75 <callout arearefs="plural.stage1.2.3"> … … 78 78 </callout> 79 79 <callout arearefs="plural.stage1.2.4"> 80 <para>你可能认为它可以将 <literal>caps</literal> 变成 <literal>oaps</literal>,但� ��是这样。 <literal>re.sub</literal> 替换 <emphasis>所有</emphasis> 的匹配项,并不只是第一个匹配项。 因此正则表达式将会把 <literal>caps</literal> 变成 <literal>oops</literal>。因为, <literal>c</literal> 和 <literal>a</literal> 都被转换为 <literal>o</literal>了。</para>80 <para>你可能认为它可以将 <literal>caps</literal> 变成 <literal>oaps</literal>,但���实并非如此。 <literal>re.sub</literal> 替换 <emphasis>所有</emphasis> 的匹配项,并不只是第一个匹配项。 因此正则表达式将会把 <literal>caps</literal> 变成 <literal>oops</literal>。因为, <literal>c</literal> 和 <literal>a</literal> 都被转换为 <literal>o</literal>了。</para> 80 80 </callout> 81 81 </calloutlist> … … 102 102 </callout> 103 103 <callout arearefs="plural.stage1.3.2"> 104 <para>仔细看看,这是另一个新的内容。 <literal>^</literal> 是方括号里面的第一个字符,这有特别的含义:否定。 <literal>[^abc]</literal> 意味着 <quote> 除 <literal>a</literal>、 <literal>b</literal>、 和 <literal>c</literal> <emphasis>以外的</emphasis> 任意单字符</quote>。 所以, <literal>[^aeioudgkprt]</literal> 意味着除 <literal>a</literal>、 <literal>e</literal>、 <literal>i</literal>、 <literal>o</literal>、 <literal>u</literal>、 <literal>d</literal>、 <literal>g</literal>、 <literal>k</literal>、 <literal>p</literal>、 <literal>r</literal> 和 <literal>t</literal> 以外的任意字符。 这个字符之后应该跟着一个 <literal>h</literal>,然后是字符串的结尾。你在寻找的 事以发音的 H 结尾的单词。</para>104 <para>仔细看看,这是另一个新的内容。 <literal>^</literal> 是方括号里面的第一个字符,这有特别的含义:否定。 <literal>[^abc]</literal> 意味着 <quote> 除 <literal>a</literal>、 <literal>b</literal>、 和 <literal>c</literal> <emphasis>以外的</emphasis> 任意单字符</quote>。 所以, <literal>[^aeioudgkprt]</literal> 意味着除 <literal>a</literal>、 <literal>e</literal>、 <literal>i</literal>、 <literal>o</literal>、 <literal>u</literal>、 <literal>d</literal>、 <literal>g</literal>、 <literal>k</literal>、 <literal>p</literal>、 <literal>r</literal> 和 <literal>t</literal> 以外的任意字符。 这个字符之后应该跟着一个 <literal>h</literal>,然后是字符串的结尾。你在寻找的是以发音的 H 结尾的单词。</para> 104 104 </callout> 105 105 <callout arearefs="plural.stage1.3.3"> … … 149 149 </callout> 150 150 <callout arearefs="plural.stage1.5.2"> 151 <para>顺便提一下,可以将两个正则表达式(一个确定规则适用与否,一个应用规则)合并在一起成为一个正则表达式。 这便是合并后的样子。 它的大部分已经很熟悉:你应用的是在 <xref linkend="re.phone"/> 学过的记忆组(remembered group)记住 <literal>y</literal> 之前的字符。然后� ��替换字符串,你使用一个新的语法 <literal>\1</literal>,这意味着: <quote>嘿!记得前面的第一个组吗? 把它放这儿</quote>。 就此而言,记住了 <literal>y</literal> 之前的 <literal>c</literal> ,然后你做替换工作,你将 <literal>c</literal> 替换到 <literal>c</literal> 的位置,并将 <literal>ies</literal> 替换到 <literal>y</literal> 的位置。 (如果你有不只一个组则可以使用 <literal>\2</literal> 或者 <literal>\3</literal> 等等。)</para>151 <para>顺便提一下,可以将两个正则表达式(一个确定规则适用与否,一个应用规则)合并在一起成为一个正则表达式。 这便是合并后的样子。 它的大部分已经很熟悉:你应用的是在 <xref linkend="re.phone"/> 学过的记忆组(remembered group)记住 <literal>y</literal> 之前的字符。然后���替换字符串,你使用一个新的语法 <literal>\1</literal>,这意味着: <quote>嘿!记得前面的第一个组吗? 把它放这儿</quote>。 就此而言,记住了 <literal>y</literal> 之前的 <literal>c</literal> ,然后你做替换工作,你将 <literal>c</literal> 替换到 <literal>c</literal> 的位置,并将 <literal>ies</literal> 替换到 <literal>y</literal> 的位置。 (如果你有不只一个组则可以使用 <literal>\2</literal> 或者 <literal>\3</literal> 等等。)</para> 151 151 </callout> 152 152 </calloutlist> … … 201 201 <calloutlist> 202 202 <callout arearefs="plural.stage2.1.1"> 203 <para>这个版本看起来更加复杂 (至少是长了),但做的工作没有变化:试图顺序匹配四种不同规则,并在匹配时应用恰当的正则表达式。 不同之处在于,每个独立的匹配和应用规则都在自己的 [todo]方程中定义,并且这些方程列于 <varname>rules</varname> 变量这个元组的元组之中。</para>203 <para>这个版本看起来更加复杂 (至少是长了),但做的工作没有变化:试图顺序匹配四种不同规则,并在匹配时应用恰当的正则表达式。 不同之处在于,每个独立的匹配和应用规则都在自己的函数中定义,并且这些函数列于 <varname>rules</varname> 变量这个元组的元组之中。</para> 203 203 </callout> 204 204 <callout arearefs="plural.stage2.1.2"> … … 229 229 </programlisting> 230 230 </example> 231 <para>这里的好处在于 <function>plural</function> 函数现在被简化了。 它以普通的方法反复使用其它地方定义的规则。 获得一个匹配规则,匹配吗? 调用并应用规则。 规则可以在任意地方以任意方法定义, <function>plural</function> 函数对此并不[todo](关心?)在乎。</para> 232 <para>现在,添加这个抽象过程值得吗? 嗯... 还不值。 让我们看看如何[todo]向方程添加一个新的规则。 啊哈,在先前的范例中,需要向 <function>plural</function> 函数添加一个 &if; 语句;在这个例子中,需要增加两个函数: <function>match_foo</function> 和 <function>apply_foo</function>,然后更新 <varname>rules</varname> 列表指定在什么相对位置调用这个新匹配和新规则应用。</para> 231 <para>这里的好处在于 <function>plural</function> 函数现在被简化了。 它以普通的方法反复使用其它地方定义的规则。 获得一个匹配规则,匹配吗? 调用并应用规则。 规则可以在任意地方以任意方法定义, <function>plural</function> 函数对此并不关心。</para> 232 <para>现在,添加这个抽象过程值得吗? 嗯... 还不值。 让我们看看如何向函数添加一个新的规则。 啊哈,在先前的范例中,需要向 <function>plural</function> 函数添加一个 &if; 语句;在这个例子中,需要增加两个函数: <function>match_foo</function> 和 <function>apply_foo</function>,然后更新 <varname>rules</varname> 列表指定在什么相对位置调用这个新匹配和新规则应用。</para> 233 233 <para>这其实不过是步入下一节的一个基石。让我们继续。</para> 234 234 </section> … … 239 239 <abstract> 240 240 <title/> 241 <para>将每个匹配和规则应用分别制作成函数没有必要。 你从来不会直接调用它们:你把它们定义于 <varname>rules</varname> 列表之中并从那里调用它们。 让我们隐去他们的函数名而抓住规则定义主线。</para> 241 <para>将每个匹配和规则应用分别制作成函数没有必要。 你从来不会直接调用它们:你把它们定义于 <varname>rules</varname> 列表之中并从那里调用它们。 让我们隐去他们的函数名而抓住规则定义的主线。</para> 241 241 </abstract> 242 242 <example> … … 262 262 </calloutlist> 263 263 </example> 264 <para>现在添加一条新的规则,所有你要做的就是直接在 <varname>rules</varname> 列表之中定义函数:一个匹配规则,一个应用规则。 这样内嵌的规则 方程定义方法使得没必要的重复很容易发现。 你有四对函数,它们采用相同的模式。 匹配函数就是调用 <function>re.search</function>,应用函数就是调用 <function>re.sub</function>。 让我们提炼出这些共同点。</para>264 <para>现在添加一条新的规则,所有你要做的就是直接在 <varname>rules</varname> 列表之中定义函数:一个匹配规则,一个应用规则。 这样内嵌的规则函数定义方法使得没必要的重复很容易被发现。 你有四对函数,它们采用相同的模式。 匹配函数就是调用 <function>re.search</function>,应用函数就是调用 <function>re.sub</function>。 让我们提炼出这些共同点。</para> 264 264 </section> 265 265 … … 284 284 <calloutlist> 285 285 <callout arearefs="plural.stage4.1.1"> 286 <para><function>buildMatchAndApplyFunctions</function> 是一个动态生成其它函数的函数。 它将 <varname>pattern</varname>, <varname>search</varname> 和 <varname>replace</varname> ( [todo]实际上是把一个元组,但很快就会变得不止于此),通过使用 &lambdafunction; 语法构建一个接受单参数(<varname>word</varname>)并以传递给 <function>buildMatchAndApplyFunctions</function> 的 <varname>pattern</varname> 和 传递给新函数的 <varname>word</varname> 调用 <function>re.search</function> 的匹配函数! 哇塞!</para>286 <para><function>buildMatchAndApplyFunctions</function> 是一个动态生成其它函数的函数。 它将 <varname>pattern</varname>, <varname>search</varname> 和 <varname>replace</varname> (实际上是一个元组,但很快就会变得不止于此),通过使用 &lambdafunction; 语法构建一个接受单参数(<varname>word</varname>)并以传递给 <function>buildMatchAndApplyFunctions</function> 的 <varname>pattern</varname> 和 传递给新函数的 <varname>word</varname> 调用 <function>re.search</function> 的匹配函数! 哇塞!</para> 286 286 </callout> 287 287 <callout arearefs="plural.stage4.1.2"> 288 <para>构建应用规则函数的方法相同。 应用规则函数是一个接受单参数并以传递给 <function>buildMatchAndApplyFunctions</function> 的 <varname>search</varname> 和 <varname>replace</varname> 以及传递给这个应用规则函数的 <varname>word</varname> 调用 <function>re.sub</function> 的函数。在一个动态函数中应用外部参数值的技术被称作 <emphasis> [todo]闭宝(closures)</emphasis>。你实际上是在应用规则函数中定义常数:接受一个参数(<varname>word</varname>),但随后它与定义应用规则函数时设置的另外两个值 (<varname>search</varname> 和 <varname>replace</varname>)一起工作。</para>288 <para>构建应用规则函数的方法相同。 应用规则函数是一个接受单参数并以传递给 <function>buildMatchAndApplyFunctions</function> 的 <varname>search</varname> 和 <varname>replace</varname> 以及传递给这个应用规则函数的 <varname>word</varname> 调用 <function>re.sub</function> 的函数。在一个动态函数中应用外部参数值的技术被称作 <emphasis>闭合(closures)</emphasis>。你实际上是在应用规则函数中定义常数:接受一个参数(<varname>word</varname>),但随后它与定义应用规则函数时设置的另外两个值 (<varname>search</varname> 和 <varname>replace</varname>)一起工作。</para> 288 288 </callout> 289 289 <callout arearefs="plural.stage4.1.3"> … … 303 303 <calloutlist> 304 304 <callout arearefs="plural.stage4.2.1"> 305 <para>我们的复数化规则现在被定义成一组字符串(不是函数)。 第一个字符串是你在调用 <function>re.search</function> 时使用的正则表达式;第二个和第三个字符串是 是你在通过调用 <function>re.sub</function> 来应用规则将名词变为复数时使用的搜索和替换表达式。 </para>305 <para>我们的复数化规则现在被定义成一组字符串(不是函数)。 第一个字符串是你在调用 <function>re.search</function> 时使用的正则表达式;第二个和第三个字符串是你在通过调用 <function>re.sub</function> 来应用规则将名词变为复数时使用的搜索和替换表达式。 </para> 305 305 </callout> 306 306 <callout arearefs="plural.stage4.2.2"> … … 361 361 </callout> 362 362 </calloutlist> 363 <para>现在,让我们回过头看一看这个元组自动展开技巧的必要性。 <varname>patterns</varname> 是一个元组列表,并且每个元组都有三个元� ��。调用 <literal>map(buildMatchAndApplyFunctions, patterns)</literal>,这并<emphasis>不</emphasis> 意味着是以三个参数调用 <function>buildMatchAndApplyFunctions</function>。 使用 <function>map</function> 映射一个列表到函数时,通常使用单参数:列表中的每个元素。 就 <varname>patterns</varname> 而言, 列表的每个元素都是一个元组,所以 <function>buildMatchAndApplyFunctions</function> 经常是以元组来调用,在 <function>buildMatchAndApplyFunctions</function> 中使用元组自动展开技巧将元素赋值给可以被使用的变量。</para>363 <para>现在,让我们回过头看一看这个元组自动展开技巧的必要性。 <varname>patterns</varname> 是一个元组列表,并且每个元组都有三个元���。调用 <literal>map(buildMatchAndApplyFunctions, patterns)</literal>,这并<emphasis>不</emphasis> 意味着是以三个参数调用 <function>buildMatchAndApplyFunctions</function>。 使用 <function>map</function> 映射一个列表到函数时,通常使用单参数:列表中的每个元素。 就 <varname>patterns</varname> 而言, 列表的每个元素都是一个元组,所以 <function>buildMatchAndApplyFunctions</function> 经常是以元组来调用,在 <function>buildMatchAndApplyFunctions</function> 中使用元组自动展开技巧将元素赋值给可以被使用的变量。</para> 363 363 </example> 364 364 </section> … … 414 414 </callout> 415 415 <callout arearefs="plural.stage5.1.5"> 416 <para>如果 <varname>patterns</varname> 是一个元组列表,那么 <varname>rules</varname> 就可以通过一个个调用 <function>buildRule</function> 动态地 声称函数列表。 调用 <function>buildRule(('[sxz]$', '$', 'es'))</function> 返回一个接受单参数 <varname>word</varname> 的函数。 当返回的函数被调用,则将执行 <literal>re.search('[sxz]$', word) 和 re.sub('$', 'es', word)</literal>。</para>416 <para>如果 <varname>patterns</varname> 是一个元组列表,那么 <varname>rules</varname> 就可以通过一个个调用 <function>buildRule</function> 动态地生成函数列表。 调用 <function>buildRule(('[sxz]$', '$', 'es'))</function> 返回一个接受单参数 <varname>word</varname> 的函数。 当返回的函数被调用,则将执行 <literal>re.search('[sxz]$', word) 和 re.sub('$', 'es', word)</literal>。</para> 416 416 </callout> 417 417 <callout arearefs="plural.stage5.1.6"> 418 <para>因为你现在构建的是一个匹配和规则应用� ��一的函数,你需要分别调用它们。 仅仅是调用函数,如果返回了内容,那么返回的便是复数;如果没有返回(也就是返回了&none;),那么该规则未能匹配,那么应该尝试其他规则。</para>418 <para>因为你现在构建的是一个匹配和规则应用���一的函数,你需要分别调用它们。 仅仅是调用函数,如果返回了内容,那么返回的便是复数;如果没有返回(也就是返回了&none;),那么该规则未能匹配,那么应该尝试其他规则。</para> 418 418 </callout> 419 419 </calloutlist> … … 431 431 <abstract> 432 432 <title/> 433 <para>现在你已准备好探讨生成器(Generator )了 .</para>433 <para>现在你已准备好探讨生成器(Generator )了。</para> 433 433 </abstract> 434 434 <example> … … 478 478 </callout> 479 479 <callout arearefs="plural.stage6.2.2"> 480 <para>建立一个 <function>make_counter</function> 生成器的实例, [todo]只需像调用任何其他函数。 注意这并没有真正的执行函数代码。 <function>make_counter</function> 第一行的 &print; 语句是一个语句,但是没有任何内容被打印就可以说明这一点。</para>480 <para>建立一个 <function>make_counter</function> 生成器的实例,并像调用任何其他函数一样调用之。 注意这并没有真正的执行函数代码。 <function>make_counter</function> 第一行的 &print; 语句是一个语句,但是没有任何内容被打印就可以说明这一点。</para> 480 480 </callout> 481 481 <callout arearefs="plural.stage6.2.3"> … … 529 529 </callout> 530 530 <callout arearefs="plural.stage6.4.2"> 531 <para>每轮 &for; 循环 <varname>n</varname> 都从 <function>fibonacci</function> 的 &yield; 语句获得一个新的值。 当 <function>fibonacci</function> 超出数字限定(<varname>a</varname> 达到超过<varname>max</varname> 你在这里限定的<literal>1000</literal>)很自然地退出 &for; 循环。</para>531 <para>每轮 &for; 循环 <varname>n</varname> 都从 <function>fibonacci</function> 的 &yield; 语句获得一个新的值。 当 <function>fibonacci</function> 超出数字限定(<varname>a</varname> 超过 <varname>max</varname> 你在这里限定的是 <literal>1000</literal>)很自然地退出 &for; 循环。</para> 531 531 </callout> 532 532 </calloutlist> … … 549 549 <calloutlist> 550 550 <callout arearefs="plural.stage6.5.1"> 551 <para><literal>for line in file(...)</literal> 是从文件中一行行读取的通用方法,每次一行。 它 的正常工作是因为 <emphasis><function>file</function> 实际上返回一个生成器</emphasis>, 它的 <function>next()</function> 方法返回文件中的下一行。 简直太酷了,光是想想就让我满头大汗。</para>551 <para><literal>for line in file(...)</literal> 是从文件中一行行读取的通用方法,每次一行。 它能正常工作是因为 <emphasis><function>file</function> 实际上返回一个生成器</emphasis>, 它的 <function>next()</function> 方法返回文件中的下一行。 简直太酷了,光是想想就让我满头大汗。</para> 551 551 </callout> 552 552 <callout arearefs="plural.stage6.5.2"> 585 585 <listitem><para>构建 <link linkend="plural.stage6">生成器</link>,进行逻辑递增操作并在每次调用时返回不同值的恢复执行函数。</para></listitem> 586 586 </itemizedlist> 587 <para>抽象化,动态构建函数,构建闭合以及应用生成器能够使你的代码更加简单� ��、可读化、灵活化。 在简洁和功能实现是需要你从中平衡的。</para>587 <para>抽象化,动态构建函数,构建闭合以及应用生成器能够使你的代码更加简单���、可读化、灵活化。 你需要在简洁和功能实现中进行平衡。</para> 587 587 </section> 588 588 </chapter>