Python--Errors,User-defined Exceptions

来源:互联网 发布:淘宝卖家上传宝贝软件 编辑:程序博客网 时间:2024/05/24 07:24

NOTE:我学习Python希望深入再深入。不满足于浮于表面,采用乱序补漏洞法,基于官方英文手册,仔细学习实验。文章所列代码都是个人所写!!

8. Errors And Exceptions

There are (at least) two distinguishable kinds of errors: syntax errors and exceptions.

8.2 Exception

The string printed as the exception type is the name of the built-in exception that occurred. This is true for all built-in exceptions, but need not be true for user-defined exceptions (although it is a useful convention).

这句话翻译下:打印出的字符串与所发生异常的类型对应,这对于所有的內建异常成立,但是对于用户定义的异常则没有必要。

8.3 Handling Exception

If an exception occurs which does not match the exception named in the except clause, it is passed on to outer try statements; if no handler is found, it is an unhandled exception and execution stops with a message as shown above.

作为比较重要的一个nested 概念,可以做个试验验证下:

def test():  try:    try:      raise IOError    except ValueError:      print "ValueError happened\n"  except IOError:      print "Ioerror pass to outer try statements\n"test()

结果如下:

[root@localhost ~]# python2.7 test1.pyIoerror pass to outer try statements

接下来对于官网的列子进行一些批注:

import sys...except:    print "Unexpected error:", sys.exc_info()[0]#    raise

对于sys.exc_info()我需要稍微深入下:

If no exception is being handled anywhere on the stack, a tuple containing three None values is returned. Otherwise, the values returned are (type, value, traceback). Their meaning is: type gets the exception type of the exception being handled (a class object); value gets the exception parameter (its associated value or the second argument to raise, which is always a class instance if the exception type is a class object); traceback gets a traceback object (see the Reference Manual) which encapsulates the call stack at the point where the exception originally occurred.

随便试下效果:

>>> import sys>>> def test():...     try:...             raise IOError...     except:...             print sys.exc_info()...>>> test()(<type 'exceptions.IOError'>, IOError(), <traceback object at 0x7f566a98b758>)#IOError()已经实例化了该对象。

再次看一个用法:

except:      ...      raise

注意捕获之后,又再次生产该exception!那么这样的用法就是试探异常的种类吗?

一个特性:实例化Exception:

  • 实例化exception,并且存储参数
  • 参数的类型和出现方式取决于exception的类型。
def test():    try :        raise IOError('hello')    except IOError as a :        print a        print a.argsdef test1():    try :        a=IOError('world')        raise  a    except IOError:        print a        print a.args#third testtest()test1()

结果:

[root@localhost ~]# python2.7 test.pyhello('hello',)world('world',)

8.4. Raising Exceptions

The sole argument to raise indicates the exception to be raised. This must be either an exception instance or an exception class (a class that derives from Exception). If an exception class is passed, it will be implicitly instantiated by calling its constructor with no arguments:

有个概念必须清楚:

raise IOErrorraise IOError('argument')

两者等价,所以说raise后面可以跟class,但是其实前者也会call constructor去实例化Exception.

8.5. User-defined Exceptions

自定义的Exception需要遵循:

  • derive from the Exception class
  • redefine your own constructor

8.6. Defining Clean-up Actions

In real world applications, the finally clause is useful for releasing external resources (such as files or network connections), regardless of whether the use of the resource was successful

finally:让我总结的话,就是一切结束try语句块的情况,都会最终执行finally。

思考:如果我们按照顺序结构安排我们的执行语句在try-except之间,而except负责处理各种异常抛出,是不是就不用else,finally语句了。
针对上面的话,我简单的写个伪代码来体会下:

def test()    try        顺序语句1        顺序语句2        结果    except 异常1 :        处理语句1:    except 异常2:        处理语句2def test()    try        顺序语句1    except 异常1 :        处理语句1:    except 异常2:        处理语句2    else:        顺序语句2:    finally:        结果    

很有意思吧,后者的层次更加清晰。

9.8. Exceptions Are Classes Too

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:

这个特性很重要的一个说法就是,except 异常,捕获异常的基类或者衍生类。但是反之,如果except 异常是衍生类,则只捕获衍生类!测试就不做了,很容易。

9.9. Iterators

官方的很有意思告诉我们几件事情:

  • for采用的实现是通过调用iter()返回一个object,然后调用object.next method去迭代,当超过index的范围就会rasie一个异常来终止for.
  • 我们自己可以的类可以仿照这样的例子来支持迭代特性。
    • 该自定义类要含有iter(),next()方法

实验:

class owniter:    def __init__(self,a):        self.data=a        self.datalen=len(a)        self.index=0    def __iter__(self):        return self    def next(self):        if self.index == self.datalen :            raise StopIteration        self.index =self.index+1        return self.data[self.index-1]for i in owniter('qwm'):    print i

结果:

[root@localhost ~]# python2.7 hugu.pyqwm

我比较在意的是变量的作用域,这点对于编程中该如何定义使用变量很关键。这里以后再深入!

9.10. Generators

Generators are a simple and powerful tool for creating iterators. They are written like regular functions but use the yield statement whenever they want to return data. Each time next() is called on it, 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:

What makes generators so compact is that the iter() and next() methods are created automatically.

上面的话,就是generators和iterators的关系,以及为什么generator is so compact!!!
改写上面的实验代码:

def  owniter(data):    for i in range(0,len(data),1)        yield data[i]for i in owniter('qwm'):    print i

结果:

[root@localhost ~]# python2.7 test2.pyqwm

我无心深入太多细节但是,有些地方需要仔细回顾下:

  • range返回list,如果采用xrange此时返回iterators,两者在内存占用,和执行效率上有本质区别。
  • generator的使用在于我们希望next发生在什么时候,当然next这样的方法已经自动生成了。
  • generator experssion 的概念,目前就到这里吧。
原创粉丝点击