字典取键值对当在字典中循环时,用 items 方法可将关键字和对应的值同时取出 >>> knights = {'gallahad': 'the pure', 'robin': 'the brave'} >>> for k, v in knights.items: ... print异常处理try … except 语句有一个可选的 else 子句,在使用时必须放在所有的 except 子句后面。对于在 try 子句不引发异常时必须执行的代码来说很有用 for arg in sys.argv[1:]: try: f = open except OSError: print else: print), 'lines') f.close@property使用Python内置的@property装饰器就是负责把一个方法变成属性调用的: class Student: @property def score: return self._score @score.setter def score: if not isinstance: raise ValueError if value < 0 or value > 100: raise ValueError self._score = value还可以定义只读属性,只定义getter方法,不定义setter方法就是一个只读属性: class Student: @property def birth: return self._birth @birth.setter def birth: self._birth = value @property def age: return 2015 - self._birth定制类怎么才能打印一个对象好看呢?只需要定义好__str__方法,返回一个好看的字符串就可以了 >>> class Student: ... def __init__: ... self.name = name ... def __str__: ... return 'Student object ' % self.name ... >>> print) Student object 直接敲变量不用print,打印出来的实例还是不好看: >>> s = Student >>> s <__main__.Student object at 0x109afb310>再定义一个__repr__。
但是通常__str__和__repr__代码都是一样的,所以,有个偷懒的写法: class Student: def __init__: self.name = name def __str__: return 'Student object ' % self.name __repr__ = __str__iter如果一个类想被用于for ... in循环,类似list或tuple那样,就必须实现一个__iter__方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的__next__方法拿到循环的下一个值,直到遇到StopIteration错误时退出循环。

我们以斐波那契数列为例,写一个Fib类,可以作用于for循环: class Fib: def __init__: self.a, self.b = 0, 1 # 初始化两个计数器a,b def __iter__: return self # 实例本身就是迭代对象,故返回自己 def __next__: self.a, self.b = self.b, self.a + self.b # 计算下一个值 if self.a > 100000: # 退出循环的条件 raise StopIteration return self.a # 返回下一个值异步IOasyncio是Python 3.4版本引入的标准库,直接内置了对异步IO的支持。asyncio的编程模型就是一个消息循环。我们从asyncio模块中直接获取一个EventLoop的引用,然后把需要执行的协程扔到EventLoop中执行,就实现了异步IO。
用asyncio实现Hello world代码如下: import asyncio @asyncio.coroutine def hello: print # 异步调用asyncio.sleep: r = yield from asyncio.sleep print # 获取EventLoop: loop = asyncio.get_event_loop # 执行coroutine loop.run_until_complete) loop.close@asyncio.coroutine把一个generator标记为coroutine类型,然后,我们就把这个coroutine扔到EventLoop中执行。
hello会首先打印出Hello world!,然后,yield from语法可以让我们方便地调用另一个generator。由于asyncio.sleep也是一个coroutine,所以线程不会等待asyncio.sleep,而是直接中断并执行下一个消息循环。当asyncio.sleep返回时,线程就可以从yield from拿到返回值,然后接着执行下一行语句。
把asyncio.sleep看成是一个耗时1秒的IO操作,在此期间,主线程并未等待,而是去执行EventLoop中其他可以执行的coroutine了,因此可以实现并发执行。我们用Task封装两个coroutine试试: import threading import asyncio @asyncio.coroutine def hello: print' % threading.currentThread) yield from asyncio.sleep print' % threading.currentThread) loop = asyncio.get_event_loop tasks = [hello, hello] loop.run_until_complete) loop.close观察执行过程: Hello world! >) Hello world! >) Hello again! >) Hello again! >)由打印的当前线程名称可以看出,两个coroutine是由同一个线程并发执行的。
如果把asyncio.sleep换成真正的IO操作,则多个coroutine就可以由一个线程并发执行。
我们用asyncio的异步网络连接来获取sina、sohu和163的网站首页: import asyncio @asyncio.coroutine def wget: print connect = asyncio.open_connection reader, writer = yield from connect header = 'GET / HTTP/1.0rnHost: %srnrn' % host writer.write) yield from writer.drain while True: line = yield from reader.readline if line == b'rn': break print.rstrip)) # Ignore the body, close the socket writer.close loop = asyncio.get_event_loop tasks = [wget for host in ['www.sina.com.cn', 'www.sohu.com', 'www.163.com']] loop.run_until_complete) loop.close执行结果如下: wget www.sohu.com... wget www.sina.com.cn... wget www.163.com... www.sohu.com header > HTTP/1.1 200 OK www.sohu.com header > Content-Type: text/html ... www.sina.com.cn header > HTTP/1.1 200 OK www.sina.com.cn header > Date: Wed, 20 May 2015 04:56:33 GMT ... www.163.com header > HTTP/1.0 302 Moved Temporarily www.163.com header > Server: Cdn Cache Server V2.0 ...可见3个连接由一个线程通过coroutine并发完成。


