python---高级特性

##################################
############### 迭代 ##############
##################################
1.迭代定义
可以通过 for 循环来遍历这个 list 或 tuple,这种遍历我们称为迭代(Iteration)

2.判断可迭代对象
方法是通过 collections 模块的 Iterable 类型判断
In [1]: from collections import Iterable

In [2]: isinstance('abc',Iterable)
Out[2]: True

In [3]: isinstance('{"name":"fentiao"}',Iterable)
Out[3]: True

In [4]: isinstance([1,2,3],Iterable)
Out[4]: True

In [5]: isinstance(1,Iterable)
Out[5]: False


3.字典的迭代

1)默认情况下,dict 迭代的是 key:
In [1]: d = {'name':'fentiao','age':5,'gender':'male'}

In [2]: for k in d:
   ...:     print k
   ...:     
gender
age
name

In [3]: for k,v in d:                                   
   ...:     print k,v
   ...:     
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-3-57f4828128ce> in <module>()
----> 1 for k,v in d:
      2     print k,v
      3

ValueError: too many values to unpack

2)如果要迭代 value:
In [4]: for k,v in d.iteritems():
   ...:     print k,v
   ...:     
gender male
age 5
name fentiao


4.list实现下标循环

python内置的枚举方法enumerate,把一个 list 变成索引­元素对
In [5]: for i,value in enumerate([1,2,3,4]):
   ...:     print i,value
   ...:     
0 1
1 2
2 3
3 4


5.for 循环里,同时引用了两个变量,实现迭代显示

In [6]: for x,y in [(1,2),(2,3),(3,4)]:
   ...:     print x,y
   ...:     
1 2
2 3
3 4


##############################

########## 列表生成式 #########
##############################
1.列表生成式定义
列表生成式是Python 内置的非常简单却强大的可以用来创建 list的生成式
思考:
要生成 list [1, 2, 3, 4, 5, 6, 7] 可以用 range(1, 8)
但如果要生成 [1x1, 2x2, 3x3, ..., 7x7] 怎么做?
方法一:for循环
In [7]: li = []

In [8]: for x in range(1,8):
   ...:     li.append(x*x)
   ...:     

In [9]: li
Out[9]: [1, 4, 9, 16, 25, 36, 49]

方法二:列表生成式
In [10]: [x*x for x in range(1,8)]
Out[10]: [1, 4, 9, 16, 25, 36, 49]

循环太繁琐,而列表生成式则可以用一行语句代替循环生成上面的 list.

2.列表生成式嵌套语句
1)生成20以内所有偶数的平方:
In [11]: [ i*i for i in range(0,20) if i %2 == 0 ]
Out[11]: [0, 4, 16, 36, 64, 100, 144, 196, 256, 324]


2)生成‘ABC’与‘123’的全排列:

In [13]: [i+n for i in '123' for n in 'ABC']
Out[13]: ['1A', '1B', '1C', '2A', '2B', '2C', '3A', '3B', '3C']


3.列表生成式使用两个变量来生成list

1)生成字典的的内容,格式为‘key=value’,返回其列表格式
d = {'name':'hello','age':'5'}
print [ k+'='+v for k,v in d.items()]
结果:['age=5', 'name=hello']


2)将list中所有的字符串变为小写字母

li = ['HEllo', 'World', 1]
print [i.lower() for i in li if isinstance(i, str)]
结果:['hello', 'world']


##############################

############ 生成器 ###########
##############################
1.为什么需要生成器
• 通过列表生成式,我们可以直接创建一个列表,受到内存限制,列表容量肯定是有限的;
• 列表生成式如果只需要前几个元素,浪费内存空间;

2.生成器含义
   在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的 list,从而节省大量的空间。在 Python 中,这种一边循环一边计算的机制,称为生成器(Generator)

3.创建生成器
把一个列表生成式的 [] 改成 ()

4.访问生成器
1)使用g.next()方法依次读取元素(麻烦)
2)使用 for 循环(推荐)
In [2]: l = [i for i in range(10)]    # 列表生成式
In [3]: l
Out[3]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [4]: g = (i for i in range(10))    # 生成器
In [5]: g.next()            # g.next()方法依次读取
Out[5]: 0
In [6]: g.next()
Out[6]: 1
In [7]: g.next()
Out[7]: 2
In [8]: for i in g:            # for 循环
   ...:        print i
   ...:
3
4
5
6
7
8
9


5.手动实现生成器

1)定义一函数fib,实现斐波那契数列(Fibonicci):1, 1, 2, 3, 5, 8, 13, 21....
# fib 函数定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,逻辑非常类似generator。
def fib(max):
    n,a,b = 0,0,1
    while n < max:
        print b
        a,b = b,a+b
        n += 1
fib(6)


# 要把 fib 函数变成 generator,只需要把print b 改为 yield b 就可以.

def fib(max):
    n,a,b = 0,0,1
    while n < max:
        yield b
        a,b = b,a+b
        n += 1
for x in fib(6):
    print x


2)如何理解关键字yield和next()

generator函数在每次调用next() 的时候执行,遇到 yield 语句返回,再次执行时从上次返回的
yield 语句处继续执行
def hello():
    print 'a'
    yield  1
    print 'b'
    yield  2
    print 'c'
    yield  3

a = hello()
a.next()    # 第一次调用next(),进入generator函数,函数顺序执行,遇到yield 1 语句返回'a'
a.next()    # 第二次调用next(),进入generator函数,函数顺序执行,遇到yield 2 语句返回'b'
a.next()    # 第三次调用next(),进入generator函数,函数顺序执行,遇到yield 3 语句返回'c'




6. 通过yield实现单线程的并发运算

异步I/O模型epoll          http   nginx  tomcat
import time
def consumer(name):
    print '%s 准备吃午饭了!'%(name)
    while True:
        fentiao = yield        3# 遇到yield返回到c1.next()继续执行producer('Mary')   
                5# 遇到yield返回到c2.next()继续执行producer('Mary')
        print ('午饭[%s]做出来了,被[%s]吃了')%(fentiao,name)
def producer(name):
    c1 = consumer('Tom')
    c2 = consumer('Jack')
    c1.next()            2# 调用c1.next(),执行consumer('Tom')
    c2.next()            4# 调用c2.next(),执行consumer('Jack')
    print '开始做午饭了。。。。'
    for i in range(1,3):
        time.sleep(1)
        print '[%s]做了两份午饭,两个人一起吃'%(name)
        c1.send(i)        6# c1.send(),返回到c1的yield 语句处继续执行consumer('Tom')
        c2.send(i)        7# c2.send(),返回到c2的yield 语句处继续执行consumer('Jack')
producer('Mary')        1# 执行producer('Mary')
结果:Tom 准备吃午饭了!
     Jack 准备吃午饭了!
     开始做午饭了。。。。
     [Mary]做了两份午饭,两个人一起吃
     午饭[1]做出来了,被[Tom]吃了
     午饭[1]做出来了,被[Jack]吃了
     [Mary]做了两份午饭,两个人一起吃
     午饭[2]做出来了,被[Tom]吃了

     午饭[2]做出来了,被[Jack]吃了