首页 > 程序开发 > Web开发 > Python > 正文
Python基础教程:异常、方法、属性和迭代器
2016-11-08 09:42:00       个评论    来源:u013980127的专栏  
收藏    我要投稿

8. 异常

8.1 基本操作

抛出异常

raise Exception('异常演示')

# 结果
Traceback (most recent call last):
  File "/xxx/07.python/project/demo/__init__.py", line 8, in 
    raise Exception('异常演示')
Exception: 异常演示

内建的异常

可以在exceptions模块找到,使用dir函数列出来。

>>> import exceptions
>>> dir(exceptions)
['ArithmeticError', 'AssertionError', ...]
类名 描述
Exception 所有异常的基类
AttributeError 特性引用或赋值失败时引发
IOError 试图打开不存在文件(包括其他情况)时引发
IndexError 使用序列中不存在的索引
KeyError 使用映射中不存在的键
NameError 找不到名字(变量)
SyntaxError 代码为错误形式
TypeError 内建操作或函数应用于错误类型的对象
ValueError 内建操作或函数应用于正确类型的对象,但该对象使用不合适的值
ZeroDivisionError 除法或模除操作的第二个参数为0

8.2 自定义异常

class SomeCustomException(Exception): pass

8.3 捕捉异常

使用try/except:

try:
    x = input("first: ")
    y = input("second: ")
    print x/y
except ZeroDivisionError, e:
    # 访问异常对象本身
    print e
except (TypeError, NameError):  # 同时捕捉多个异常
    # 向上抛出异常
    raise

# 结果1
first: 1
second: 0
The second number cant be zero!

# 结果2
first: 1
second: "how"
Traceback (most recent call last):
  File "xxx/__init__.py", line 11, in 
    print x/y
TypeError: unsupported operand type(s) for /: 'int' and 'str'

# 结果3
first: 1
second: j
Traceback (most recent call last):
  File "/xxx/__init__.py", line 10, in 
    y = input("second: ")
  File "", line 1, in 
NameError: name 'j' is not defined

8.4 else、finally

while True:
    try:
        x = input("first: ")
        y = input("second: ")
        print x / y
    except:
        print '捕捉所有异常'
    else:
        print '未发生异常时执行'
        break
    finally:
        print "总是执行"

# 结果
first: 1
second: 
捕捉所有异常
总是执行
first: 1
second: 2
0
未发生异常时执行
总是执行

8.5 新函数

函数 描述
warnings.filterwarnings(actiong, …) 用于过滤警告

9. 魔法方法、属性和迭代器

9.1 准备工作

新式类

赋值语句metaclass=type放在模块最开始,或者子类化object。

class NewStyle(object):

9.2 构造方法

class FooBar:
    def __init__(self):
        self.somevar = 42

f = FooBar()
print f.somevar

# 结果
42

9.2.1 重写构造方法

调用未绑定的超类构造方法

class Bird:
    def __init__(self):
        self.hungry = True

    def eat(self):
        if self.hungry:
            print 'Aaaah...'
            self.hungry = False
        else:
            print 'No, tks'


class SongBird(Bird):
    def __init__(self):
        Bird.__init__(self)
        self.sound = 'Squawk!'

    def sing(self):
        print self.sound

sb = SongBird()
sb.sing()
sb.eat()
sb.eat()

# 结果
Squawk!
Aaaah...
No, tks

使用super函数

__metaclass__ = type


class Bird:
    def __init__(self):
        self.hungry = True

    def eat(self):
        if self.hungry:
            print 'Aaaah...'
            self.hungry = False
        else:
            print 'No, tks'


class SongBird(Bird):
    def __init__(self):
        super(SongBird, self).__init__()
        self.sound = 'Squawk!'

    def sing(self):
        print self.sound

sb = SongBird()
sb.sing()
sb.eat()
sb.eat()

# 结果
Squawk!
Aaaah...
No, tks

9.3 成员访问

9.3.1 基本的序列和映射规则

序列和映射是对象的集合。

__len_(self):返回集合中所含项目的数量。 __getitem__(self, key):返回与所给键对应的值。 __setitem__(self, key, value):设置和key相关的value。只能为可以修改的对象定义这个方法。 __delitem__(self, key):对一部分对象使用del语句时被调用,同时必须删除和元素相关的键。


注意:

对于序列,如果键是负数,从末尾开始计数。 如果键是不合适的类型,会引发TypeError异常。 如果序列是正确的类型,但超出范围,引发IndexError异常。

9.3.1 子类化列表、字典和字符串

通过子类化超类,进行扩展。

class CounterList(list):
    def __init__(self, *args):
        super(CounterList, self).__init__(*args)
        self.counter = 0

    def __getitem__(self, index):
        self.counter += 1
        return super(CounterList, self).__getitem__(index)


cl = CounterList(range(10))
print cl
cl.reverse()
print cl
del cl[3:6]
print cl
print cl.counter
print cl[4] + cl[2]
print cl.counter

# 结果
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
[9, 8, 7, 3, 2, 1, 0]
0
9
2

9.4 属性

9.5.1 property函数

property函数有4个参数,分别为fget、fset、fdel和doc

class Rectangle:
    def __init__(self):
        self.width = 0
        self.height = 0

    def setSize(self, size):
        self.width, self.height = size

    def getSize(self):
        return self.width, self.height

    size = property(getSize, setSize)

r = Rectangle()
r.width = 10
r.height = 5
print r.size
r.size = 150, 100
print r.width

# 结果
(10, 5)
150

9.5.2 静态方法和类成员方法

静态方法和类成员方法分别在创建时被装入Staticmethod类型和Classmethod类型的对象中。

class MyClass:

    # 可以使用@staticmethod修饰器
    def smeth():
        print "this is a static method"
    smeth = staticmethod(smeth)

    # 可以使用@classmethod修饰器
    def cmeth(cls):
        print 'this is a class method of', cls
    cmeth = classmethod(cmeth)

MyClass.smeth()
MyClass.cmeth()

# 结果
this is a static method
this is a class method of 

9.5.3 __getattr__、__setattr__

__getattribute__(self, name):当特性name被访问时自动被调用(只能在新式类中使用)。 __getattr__(self, name):当特性name被访问且对象没有相应的特性时被自动调用。 __setattr__(self, name, value):当试图给特性name赋值时会被自动调用。 __delattr__(self, name):当试图删除特性name时被自动调用。

9.5 迭代器

9.5.1 迭代器规则

__iter__方法返回一个迭代器(iterator),如果next方法被调用,但迭代器没有值可以返回,就会引发一个StopIteration异常。

class Fibs:
    def __init__(self):
        self.a = 0
        self.b = 1

    def next(self):
        self.a, self.b = self.b, self.a + self.b
        return self.a

    def __iter__(self):
        return self

fibs = Fibs()

for f in fibs:
    if f > 1000:
        print f
        break

// 结果
1597

9.5.2 从迭代器得到序列

示例:使用list构造方法显式地将迭代器转化为列表

class TestIterator:
    value = 0

    def next(self):
        self.value += 1
        if self.value > 10:
            raise StopIteration
        return self.value

    def __iter__(self):
        return self

ti = TestIterator()
print list(ti)

// 结果
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

9.5 生成器

生成器是一种用普通的函数语法定义的迭代器。

9.5.1 创建生成器

任何包含yield语句的函数称为生成器。每次产生值(使用yield语句),函数就会被冻结:即函数停在那点等待被激活。函数被激活后就从停止的那点开始执行。

def flattern(nested):
    for sublist in nested:
        for element in sublist:
            yield element

nested = [[1, 2], [3, 4], [5]]
for num in flattern(nested):
    print num

print list(flattern(nested))

// 结果
1
2
3
4
5
[1, 2, 3, 4, 5]

9.5.2 递归生成器

def flattern(nested):
    try:
        for sublist in nested:
            for element in flattern(sublist):
                yield element
    except TypeError:
        yield nested

print list(flattern([[[1], 2], 3, 4, [5, [6, 7]], 8]))

// 结果
[1, 2, 3, 4, 5, 6, 7, 8]

9.5.3 生成器方法

生成器和“外部世界”进行交流的渠道,要注意以下两点:

外部作用域访问生成器的send方法,就像访问next方法一样,只不过前者使用一个参数(要发送的“消息”——任意对象)。 在内部则挂起生成器,yield现在作为表达式而不是语句使用,换句话说,当生成器重新运行的时候,yield方法返回一个值,也就是外部通过send方法发送的值。如果next方法被使用,那么yield方法返回None。
def repeater(value):
    while True:
        new = (yield value)
        if new is not None:
            value = new

r = repeater(43)
print r.next()
print r.send("Hello, world!")

// 结果
43
Hello, world!

生成器还有其他两个方法:

throw方法用于在生成器内引发一个异常。 close方法用于停止生成器。

9.5.4 模拟生成器

使用普通的函数模拟生成器。

def flattern(nested):
    result = []
    try:
        try: nested + ' '
        except TypeError: pass
        else: raise TypeError
        for sublist in nested:
            for element in flattern(sublist):
                result.append(element)
    except TypeError:
        result.append(nested)
    return result

print list(flattern([[[1], 2], 3, 4, [5, [6, 7]], 8]))

// 结果
[1, 2, 3, 4, 5, 6, 7, 8]

9.6 新函数

函数 描述
iter(obj) 从一个可迭代的对象得到迭代器
property(fget, fset, fdel, doc) 返回一个属性,所有的参数都是可选的
super(class, obj) 返回一个类的超类的绑定实例

点击复制链接 与好友分享!回本站首页
上一篇:Python进程和线程
下一篇:Python学习笔记:函数
相关文章
图文推荐
文章
推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训
版权所有: 红黑联盟--致力于做实用的IT技术学习网站