python-高级编程-01
【1】 列表推导
问题 我们需要一个[2,4,6,8] 这样的列表
传统写法
res = [] for i in range(10): if i %2 == 0:res.append(i) print res
当然这种写法也可以,但是效率不高 我们可以这么写
[i for i in range(10) if i%2 == 0 ]
这个就是列表推导
通常由三个部分组成 [方法 循环 条件]
就是循环 将循环的元素放到条件里比较 然后在执行方法
例子 如果我们要把
['tom,'jack','rose'] 这个列表改成 ['0:tom','1:jack','2:rose]
通常的写法是:
inter = 0 res = ["tom","jack","rose"] for i in res: res[inter] = '%d:%s'%(inter,i) inter += 1 print res
我们可以通过 enumerate 更方便的获取列表下标 从而简化代码
res = ["tom","jack","rose"] for i ,ele in enumerate(res): res[i] = "%d:%s" %(i,res[i]) print res
当然我们也可以通过列表推导搞定它
def _change_val(i,val): return "%d:%s" % (i,val) res = ["tom","jack","rose"] print [_change_val(i,ele) for i,ele in enumerate(res)]
通过列表推导的话 使得逻辑代码更加整洁 而且共享了其所需方法
我们只要是需要循环列表的时候,都要考虑是否能使用列表推导式
【2】生成器和迭代器
1》 ---迭代器
我们通过
iner 关键词可以获得一个 迭代器的对象
我们通过next 可以获取 迭代器的元素
当序列遍历完了 就会抛出异常
迭代器是通过 next() 方法和__inter__方法实现的 __inter__ 这里返回迭代器本身 我们自己也可以写一个自己的迭代器
class myinter(object): def __init__(self,step): self.step = step def next(self): if self.step == 0 : raise StopIteration self.step -= 1 return self.step def __iter__(self): return self res = myinter(5) print res.next() print res.step
1 》 生成器:
我应该这样理解 通过在函数里面加一个 yeild关键字 使之生成一个生成器
一般我们写杨辉三角是这样写的
a = [1] b = [] for i in range(5): b = [] print a a.append(0) a.insert(0, 0) for i in range(len(a) - 1): b.append(0) for i in range(len(a) - 1): b[i] = a[i] + a[i + 1] a = b
当然这是最不简洁的写法,也就是怎么像就怎么写的 如果我们用生成器的话
def fn(): a = [1] while 1: yield a a = [a[i] + a[i + 1] for i in range(len(a)-1)] a.append(1) a.insert(0,1) fn1 = fn() for i in range(10): print fn1.next()
那么生成一个 fn1 的生成器 执行到yield的时候 会阻塞直到执行next()的执行
还有其他常用的结合列表推导的方法
def fib(): a,b = 0,1 while True: yield b a,b = b,a+b fib_obl = fib() print [fib_obl.next() for i in range(10)]
这个是通过列表推导来输出我们想要生成的列表 其实yield 和return 是很近似的 都是返回值 但是yeild会阻塞在程序 这样形成了更丰富的效果 这带来的好处显而易见 我们如果需要一个非常大的列表 或者数据 那么yeild 可以避免一次性将数据放到内存
def power(values): for val in values: print 'powering %s' % val yield val def adder(values): for val in values: print 'adding to %s' % val if val % 2 == 0: yield val +1 else: yield val +2 elements = [1,4,6,7,12] res = adder(power(elements)) print res.next() print res.next()
上面程序的执行结果是
powering 1 adding to 1 3 powering 4 adding to 4 5
这个是通过 将每个序列当做迭代器,然后将其合并到一个高级函数里面 书上说 这是一种避免函数变得庞大丑陋 不可理解 但是我是有限赞同 ,也就是赞同,但是不完全赞同。
诚然这样的确会把原本复杂的功能拆分 很多非常简单的代码块 但是对初学者不够友好。
send 和close
了解了n数send(msg)。其实next()和send()在一定意义上作用是相似的,区别是send()可以传递yield表达式的值进去,而next()不能传递特定的值,只能传递None进去。因此,我们可以看做
c.next() 和 c.send(None) 作用是一样的。
def psychologist(): print 'Please tell me your problems' while 1: res=(yield) print type(res) print(res,'*******') if res is not None: if res.endswith('?'): print ("Don't ask you self too much questions") elif 'good' in res: print "A that's good .go on " elif 'bad' in res: print "Don't be so negative" free = psychologist() free.next() free.send("I feel bad") free.send("Are you OK?") free.send("I'm a good boy")
这本书上面的例子 实在太难懂了
我修改了下 使之更好理解
# -*- coding:utf-8 -*- def psychologist(): print 'start' while 1: res = yield 5 print res free = psychologist() print free.next() free.send('new value')#给表达式res赋予一个新值
res = yield 5 的意思是 表达式(yield 5)的返回值将赋值给res
这段代码的输出是
start 5 new value