python推导式与迭代器、生成器

前言

正式开始疯狂学习状态了,把考试考完之后就把刷leetcode再次提上日程!然后幸福生活还有8天!可以说是苦日子里的小甘甜

python推导式

推导式comprehensions(又称解析式),是Python的一种独有特性。推导式是可以从一个数据序列构建另一个新的数据序列的结构体。 共有三种推导,在Python2和3中都有支持:

  • 列表(list)推导式
  • 字典(dict)推导式
  • 集合(set)推导式

列表推导式

variable = [out_exp_res for out_exp in input_list out_exp ]
out_exp_res:  列表生成元素表达式,可以是有返回值的函数。
for out_exp in input_list:  迭代input_list将out_exp传入out_exp_res表达式中。
out_exp:  条件表达式,筛选数据

例子:

#打印30以内的数字,所有能被3整除的整数的平方
result = [i**2 for i in range(1,31) if i % 3 == 0]   
print(result)   
[9, 36, 81, 144, 225, 324, 441, 576, 729, 900]
#找到嵌套列表中名字含有2个'e'的所有名字
['Alice', 'Jill', 'Ana', 'Wendy', 'Jennifer', 'Sherry', 'Eve']]   
result = [i for names_a in names for i in names_a if i.lower().count('e') == 2]    
print(result)   
['Jefferson', 'Wesley', 'Steven', 'Jennifer', 'Eve']

三元运算与列表推导式(if else 放在循环语句前)

q = [x if x%3==0 else -x for x in range(1,101)]    
print(q)

字典推导式

字典推导和列表推导的使用方法是类似的,只不中括号该改成大括号。
基本格式:variable = {out_key:out_value for out_key,out_value in input_ldict if out_exp == 2}

. out_key: 返回字典结果的key
. out_value: 返回字典结果的value
. for out_key,out_value in input_list:迭代input_list将out_exp传入out_exp_res表达式中。
. if out_exp == 2:根据条件过滤哪些值可以。

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

result3 = {x.lower():q4.get(x.upper(),0)+q4.get(x.lower(),0) for x in q4.keys()}   
print(result3)   
{'b': 9, 'a': 5, 'c': 3}

集合推导式

它们跟列表推导式也是类似的。 唯一的区别在于它使用大括号{},而且列表推导式自带去重功能

l = [-1, 1 ,2 ,1]
li = {i*i for i in l}
print(li)

迭代器

迭代是Python最强大的功能之一,是访问集合元素的一种方式。
迭代器是一个可以记住遍历的位置的对象。
迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
迭代器有两个基本的方法:iter() 和 next()。

可迭代对象

凡是可以返回一个迭代器的对象都可称之为可迭代对象。

  • 如何确认一个对象是不是可迭代对象:
    可迭代对象实现了iter方法,该方法返回一个迭代器对象
  • 使用Iterable判断

    from collections.abc import Iterator
    a = range(100)
    if isinstance(a, Iterator):

    print("yes")  
    

    else:

    print("no")   
    

可迭代对象有哪些

• 容器都是可迭代对象

  • 容器(container)
  1. 容器是一种把多个元素组织在一起的数据结构,容器中的元素可以逐个地迭代获取,可以用in, not
    in关键字判断元素是否包含在容器中。
    通常这类数据结构把所有的元素存储在内存中(也有一些特例,并不是所有的元素都放在内存,比如
    迭代器和生成器对象)
  2. 在Python中,常见的容器对象有str,list, deque, tuple , …

• 此外还有更多的对象同样也是可迭代对象,比如处于打开状态的files,sockets等等。
• 凡是可以返回一个迭代器的对象都可称之为可迭代对象

什么是迭代器

迭代器是有状态的,可以被next()调用,函数调用并不断返回下一个值的对象称为迭代器(Iterator)。
任何实现了iter()和next()都是迭代器

. __iter__():返回迭代器自身   
.  __next__():返回容器中的下一个值   
. 如果容器中没有更多元素了,则抛出StopIteration异常   
. (for循环取数据遇到StopIteration时,会退出循环)   
. 所有的Iterable均可以通过内置函数iter()来转变为Iterator。   

可迭代对象和迭代器转换

iter()函数:

a = [1,2,3]
a_iter = iter(a)

生成无限序列

from  itertools import  count,cycle
counter = count(start=1, step=2)
print(counter, type(counter))
print(next(counter))
print(next(counter))
print(next(counter))
count(1, 2) <class 'itertools.count'>
1
3
5

从有序序列中生成无限序列

from  itertools import  count,cycle
counter = count(start=1, step=2)
print(counter, type(counter))
weeks = cycle([1,2,3,4,5,6,7])
print(weeks , type(weeks))
for i in range(21):
    print(next(weeks))
1
2
3
4
5
6
7
1
2

迭代器的好处

迭代器就像一个懒加载的工厂,等到有人需要的时候才给它生成值返回,没调用的时候
就处于休眠状态等待下一次调用。

生成器

生成器算得上是Python语言中最吸引人的特性之一,生成器其实是一种特殊的迭代器,
不过这种迭代器更加优雅。它不需要手动编写iter()和next()方法,只需要一个
yiled关键字。

  1. 生成器一定是迭代器(反之不成立)
  2. 因此任何生成器也是以一种懒加载的模式生成值

yield关键字

包含yield表达式的函数是特殊的函数,叫做生成器函数(generator function),被调用时将

返回一个迭代器(iterator),调用时可以使用next或send(msg)

  1. 一个生成器中可以有多个yield
  2. 一旦遇到yield,就会保存当前状态,然后返回yield后面的值

    a = [x+2 for x in range(10)]
    print(a)
    def func2():

    yield 0
    yield 1
    yield 2
    yield 3
    yield 4
    yield 5
    raise StopIteration
    yield 6
    yield 7
    

    a = func2()
    print(next(a))
    print(next(a))
    print(next(a))
    print(next(a))
    for i in a:

    print(i)
    

生成器例子

斐波拉基序列
from itertools import islice
def fib():
a = 1
b = 1
while True:
yield a
a ,b= b,a + b
print(list(islice(fib(),0,10)))
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

生成器 fib() 的执行过程
• 当执行f=fib()返回的是一个生成器对象,此时函数体中的代码并不会执行,而是首先
返回一个 iterable 对象!
• 只有显示或隐示地调用next的时候才会真正执行函数里面的代码
• 执行到语句 yield b 时,fab() 函数会返回yield后面(右边)的值,并记住当前执行的状
态
• 下次调用next时,程序流会回到 yield b 的下一条语句继续执行
• 看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过
yield 返回当前的迭代值。
• 由此可以看出,生成器通过关键字 yield 不断的将迭代器返回到内存进行处理,而不
会一次性的将对象全部放入内存,从而节省内存空间。

send数据

除了可以使用 next() 方法来获取下一个生成的值,用户还可以使用 send() 方法将一个
新的或者是被修改的值返回给生成器。除此之外,还可以使用 close() 方法来随时退出
生成器

def counter(staet_at = 0):
    count = staet_at
    while True:
        val = (yield count)
        if val is not None:
            count = val
        else :
            count += 1

count = counter(5)
print(next(count))
print(next(count))
print(next(count))
print(count.send(9))
print(next(count))
count.close()
print(next(count))

迭代器与生成器的区别

先说迭代器,对于string、list、dict、tuple等这类容器对象,使用for循环遍历是很方便的。在后台for语句对容器对象调用iter()函数,iter()是python的内置函数。iter()会返回一个定义了next()方法的迭代器对象,它在容器中逐个访问容器内元素,next()也是python的内置函数。在没有后续元素时,next()会抛出一个StopIteration异常,通知for语句循环结束。

生成器(Generator)是创建迭代器的简单而强大的工具。它们写起来就像是正规的函数,只是在需要返回数据的时候使用yield语句。每次next()被调用时,生成器会返回它脱离的位置(它记忆语句最后一次执行的位置和所有的数据值)

赏瓶可乐吧(*^▽^*)