📄 node11.html
字号:
9.8 异常也是类 Exceptions Are Classes Too</H1><P>User-defined exceptions are identified by classes as well. Using this
mechanism it is possible to create extensible hierarchies of exceptions.<P>用户自定义异常也可以是类。利用这个机制可以创建可扩展的异常体系。<P>There are two new valid (semantic) forms for the raise statement:<P>以下是两种新的有效(语义上的)异常抛出形式:<P><div class="verbatim"><pre>
raise Class, instance
raise instance</pre></div><P>In the first form, <code>instance</code> must be an instance of
<tt class="class">Class</tt> or of a class derived from it. The second form is a
shorthand for:<P>第一种形式中,<code>instance</code> 必须是 <tt class="class">Class</tt> 或其派生类的一个实例。第二种形式是以下形式的简写:<P><div class="verbatim"><pre>
raise instance.__class__, instance</pre></div><P>A class in an except clause is compatible with an exception if it is the same
class or a base class thereof (but not the other way around -- an
except clause listing a derived class is not compatible with a base
class). For example, the following code will print B, C, D in that
order:<P>发生的异常其类型如果是异常子句中列出的类,或者是其派生类,那么它们就是相符的(反过来说--发生的异常其类型如果是异常子句中列出的类的基类,它们就不相符)。例如,以下代码会按顺序打印B,C,D:<P><div class="verbatim"><pre>
class B:
pass
class C(B):
pass
class D(C):
pass
for c in [B, C, D]:
try:
raise c()
except D:
print "D"
except C:
print "C"
except B:
print "B"</pre></div><P>Note that if the except clauses were reversed (with
"<tt class="samp">except B</tt>" first), it would have printed B, B, B -- the first
matching except clause is triggered.<P>要注意的是如果异常子句的顺序颠倒过来( "<tt class="samp">execpt B</tt>" 在最前),它就会打印B,B,B--第一个匹配的异常被触发。<P>When an error message is printed for an unhandled exception which is a
class, the class name is printed, then a colon and a space, and
finally the instance converted to a string using the built-in function
<tt class="function">str()</tt>.<P>打印一个异常类的错误信息时,先打印类名,然后是一个空格、一个冒号,然后是用内置函数
<tt class="function">str()</tt> 将类转换得到的完整字符串。<P><H1><A NAME="SECTION0011900000000000000000"></A><A NAME="iterators"></A><BR>9.9 迭代器 Iterators</H1><P>By now, you've probably noticed that most container objects can be looped
over using a <tt class="keyword">for</tt> statement:<P>现在你可能注意到大多数容器对象都可以用 <code>for</code> 遍历:<P><div class="verbatim"><pre>
for element in [1, 2, 3]:
print element
for element in (1, 2, 3):
print element
for key in {'one':1, 'two':2}:
print key
for char in "123":
print char
for line in open("myfile.txt"):
print line</pre></div><P>This style of access is clear, concise, and convenient. The use of iterators
pervades and unifies Python. Behind the scenes, the <tt class="keyword">for</tt>
statement calls <tt class="function">iter()</tt> on the container object. The
function returns an iterator object that defines the method
<tt class="method">next()</tt> which accesses elements in the container one at a
time. When there are no more elements, <tt class="method">next()</tt> raises a
<tt class="exception">StopIteration</tt> exception which tells the <tt class="keyword">for</tt> loop
to terminate. This example shows how it all works:<P>这种形式的访问清晰、简洁、方便。这种迭代器的用法在 Python 中普遍而且统一。在后台,<code>for</code> 语句在容器对象中调用 <tt class="function">iter()</tt> 。 该函数返回一个定义了 <tt class="method">next()</tt> 方法的迭代器对象,它在容器中逐一访问元素。没有后续的元素时,<tt class="method">next()</tt>抛出一个 <tt class="exception">StopIteration</tt> 异常通知 <code>for</code> 语句循环结束。以下是其工作原理的示例:<P><div class="verbatim"><pre>
>>> s = 'abc'
>>> it = iter(s)
>>> it
<iterator object at 0x00A1DB50>
>>> it.next()
'a'
>>> it.next()
'b'
>>> it.next()
'c'
>>> it.next()
Traceback (most recent call last):
File "<pyshell#6>", line 1, in -toplevel-
it.next()
StopIteration</pre></div><P>Having seen the mechanics behind the iterator protocol, it is easy to add
iterator behavior to your classes. Define a <tt class="method">__iter__()</tt> method
which returns an object with a <tt class="method">next()</tt> method. If the class defines
<tt class="method">next()</tt>, then <tt class="method">__iter__()</tt> can just return <code>self</code>:<P>了解了迭代器协议的后台机制,就可以很容易的给自己的类添加迭代器行为。定义一个 <tt class="method">__iter__()</tt> 方法,使其返回一个带有 <tt class="method">next()</tt> 方法的对象。如果这个类已经定义了 <tt class="method">next()</tt>,那么 <tt class="method">__iter__()</tt> 只需要返回self:<P><div class="verbatim"><pre>
>>> class Reverse:
"Iterator for looping over a sequence backwards"
def __init__(self, data):
self.data = data
self.index = len(data)
def __iter__(self):
return self
def next(self):
if self.index == 0:
raise StopIteration
self.index = self.index - 1
return self.data[self.index]
>>> for char in Reverse('spam'):
print char
m
a
p
s</pre></div><P><H1><A NAME="SECTION00111000000000000000000"></A><A NAME="generators"></A><BR>9.10 生成器 Generators</H1><P>Generators are a simple and powerful tool for creating iterators. They are
written like regular functions but use the <tt class="keyword">yield</tt> statement whenever
they want to return data. Each time the <tt class="method">next()</tt> is called, the
generator resumes where it left-off (it remembers all the data values and
which statement was last executed). An example shows that generators can
be trivially easy to create:<P>生成器是创建迭代器的简单而强大的工具。它们写起来就像是正则函数,需要返回数据的时候使用 <tt class="keyword">yield</tt> 语句。每次 <tt class="method">next()</tt> 被调用时,生成器回复它脱离的位置(它记忆语句最后一次执行的位置和所有的数据值)。以下示例演示了生成器可以很简单的创建出来:<P><div class="verbatim"><pre>
>>> def reverse(data):
for index in range(len(data)-1, -1, -1):
yield data[index]
>>> for char in reverse('golf'):
print char
f
l
o
g</pre></div><P>Anything that can be done with generators can also be done with class based
iterators as described in the previous section. What makes generators so
compact is that the <tt class="method">__iter__()</tt> and <tt class="method">next()</tt> methods are
created automatically.<P>前一节中描述了基于类的迭代器,它能作的每一件事生成器也能作到。因为自动创建了 <tt class="method">__iter__()</tt> 和 <tt class="method">next()</tt> 方法,生成器显得如此简洁。<P>Another key feature is that the local variables and execution state
are automatically saved between calls. This made the function easier to write
and much more clear than an approach using class variables like
<code>self.index</code> and <code>self.data</code>.<P>另外一个关键的功能是两次调用之间的局部变量和执行情况都自动保存了下来。这样函数编写起来就比手动调用
<code>self.index</code> 和 <code>self.data</code> 这样的类变量容易的多。<P>In addition to automatic method creation and saving program state, when
generators terminate, they automatically raise <tt class="exception">StopIteration</tt>.
In combination, these features make it easy to create iterators with no
more effort than writing a regular function.<P>除了创建和保存程序状态的自动方法,当发生器终结时,还会自动抛出 <tt class="exception">StopIteration</tt> 异常。综上所述,这些功能使得编写一个正则函数成为创建迭代器的最简单方法。<P><BR><HR><H4>Footnotes</H4><DL><DT><A NAME="foot2455">... namespace!</A><A HREF="node11.html#tex2html9"><SUP>9.1</SUP></A></DT><DD>
Except for one thing. Module objects have a secret read-only
attribute called <tt class="member">__dict__</tt> which returns the dictionary
used to implement the module's namespace; the name
<tt class="member">__dict__</tt> is an attribute but not a global name.
Obviously, using this violates the abstraction of namespace
implementation, and should be restricted to things like
post-mortem debuggers.
</DD><DT><A NAME="foot1679">... 是它的一个属性。因此,模块的属性和模块中的全局命名有直接的映射关系:它们共享同
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -