【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