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
posted @ 2017-06-20 19:03  nerdlerss  阅读(188)  评论(0编辑  收藏  举报