Python Day 13 函数(迭代器,生成器,列表推导式,生成器表达式)

Python Day 13  函数(迭代器,生成器,列表推导式,生成器表达式)

可迭代对象

  内部含有__iter__方法的就是可迭代对象,遵循可迭代协议。实际上可迭代对象是不可以依次取值的,因为他没有__next__方法。

  for循环提供一个机制:
    1,将可迭代对象转化成迭代器。
    2,利用__next__进行取值。
    3,用try异常处理方法防止报错。

  模拟for循环

l = [1, 2, 3, 4, 5]
l_obj = l.__iter__()
while True:
    try:
        print(l_obj.__next__())
    except Exception:
        break

判断方法
  第一种方法:dir

dir
print(dir('123'))  # '__iter__'
print('__iter__' in dir([1, 2, 3]))
print('__iter__' in dir({'name':'alex'}))
print('__iter__' in dir({'name'}))
print('__iter__' in dir((1, 2, 3)))
print('__iter__' in dir(1))  # False
print('__iter__' in dir(True))  # False

  第二种方法:引入方法

    from collections import Iterable

    from collections import Iterator

from collections import Iterable
from collections import Iterator
print(isinstance('123', Iterable))
print(isinstance('123', Iterator))

  

迭代器 iterator

  可迭代对象通过.__iter__()可以转换成迭代器,满足迭代器协议。内部含有__iter__ 且 __next__方法的就是迭代器。

  1,节省内存。
  2,满足惰性机制。
  3,取值过程不可逆(一条路走到黑)。
迭代器的取值两种方法:
  方法一:__next__()
print(l_obj.__next__())
print(l_obj.__next__())
print(l_obj.__next__())
print(l_obj.__next__())

  方法二 for循环
for i in l_obj:
    print(i)
print('__next__' in dir(l_obj))

 

生成器 Generator:

生成器本质也是迭代器,生成器是自己用Python写的迭代器。
  构建方法:

    1,通过生成器函数构建。
      一个包含yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值,
      但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,
      而是得到一个可迭代的对象。每一次获取这个可迭代对象的值,就能推动函数的执行,获取新的返回值。直到函数执行结束。
      send

    2,通过生成器推导式构建。
def generator():
    print(123)
    content = yield 1
    print('=======',content)
    print(456)
    yield2

g = generator()
ret = g.__next__()
print('***',ret)
ret = g.send('hello')   #send的效果和next一样
print('***',ret)

#send 获取下一个值的效果和next基本一致
#只是在获取下一个值的时候,给上一yield的位置传递一个数据
#使用send的注意事项
    # 第一次使用生成器的时候 是用next获取下一个值
    # 最后一个yield不能接受外部的值

 

def func1():
    print(11)
    print(333)
    yield 222
    print(666)
    yield 777
g_obj = func1()  # 生成器对象 generator object  , 生成器对象不能直接打印,生成器本质也是迭代器,需要使用.__next__ 读取到yield
print(g_obj.__next__())
print(g_obj.__next__())

   



列表推导式和生成器表达式

  列表推导式 简单明了,但是占内存
  生成器表达式 节省内存,不易看出。

  1.把列表解析的[]换成()得到的就是生成器表达式

  2.列表解析与生成器表达式都是一种便利的编程方式,只不过生成器表达式更节省内存

  3.Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如, sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以,我们可以直接这样计算一系列值的和:

sum(x ** 2 for x in range(4))
 

列表推导式

  列表推导式:能用列表推导式完成的,用python代码都可以完成。

    用一句话构建一个你想要的列表。

    优点:简单,稍微难理解。

    缺点: 不能用debug。

 

[ 变量(加工后的变量) for 变量 in 可迭代对象 ]  遍历模式
li = [i for i in range(1, 12)]
print(li)

[ 变量(加工后的变量) for 变量 in 可迭代对象 if 判断] 筛选模式
names = [['Tom', 'Billy', 'Jefferson', 'Andrew', 'Wesley', 'Steven', 'Joe'],
         ['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eva']]
l3 = [ name for i in names for name in i if name.count('e') == 2]
print(l3)字典

字典推导式

  例一:将一个字典的key和value对调

mcase = {'a': 10, 'b': 34}
mcase_frequency = {mcase[k]: k for k in mcase}
print(mcase_frequency)

  例二:合并大小写对应的value值,将k统一成小写  

mcase = {'a': 10, 'b': 34, 'A': 7, 'Z': 3}
mcase_frequency = {k.lower(): mcase.get(k.lower(), 0) + mcase.get(k.upper(), 0) for k in mcase.keys()}
print(mcase_frequency)

集合推导式  

  计算列表中每个值的平方,自带去重功能

squared = {x**2 for x in [1, -1, 2]}
print(squared)
# Output: set([1, 4])

生成器表达式

  把列表解析的[]换成()得到的就是生成器表达式

  生成器对象不能直接打印,需要使用for循环配合 .__next__  读取

  

g = (i*i for i in range(1, 11))
for i in g:
    print(i)

  

posted @ 2018-05-16 19:02  eailoo  阅读(157)  评论(0编辑  收藏  举报