Python中的高级特性

迭代

迭代的含义

迭代就是一次次重复的过程,不断地将上一次的输出结果作为下一次的输入或者说是初始值。
Python中的list和tuple可以通过for循环进行遍历,这种遍历我们就称作为迭代(Interation)

在Python中迭代是通过for…in完成的,Python中的可迭代对象无论有无下标都可以进行迭代。

例如list可以用下标进行迭代,正如C语言和其他语言通过下标进行迭代,也可以不用下标进行迭代。

>>> a = [1,2,3]
>>> for i in range(3):
...     print(a[i])
...
1
2
3
>>> for item in a:
...     print(item)
...
1
2
3

Python中内置的enumerate函数可以把一个list变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身

>>> for i,v in enumerate(a):
...     print(i,v)
...
0 1
1 2
2 3

又例如dict迭代,dict默认迭代key,也可使用for value in test.values()对value进行迭代,或者使用for k,v in test.items()迭代key和value。

>>> a_dict={"name":"sakura","city":"Chengdu"}
>>> for item in a_dict:
...     print(item)
...
city
name
>>> for value in a_dict.values():
...     print(value)
...
Chengdu
sakura
>>> for k,v in a_dict.items():
...     print(k,v)
...
city Chengdu
name sakura


可以通过collections模块的Iterable类型判断一个对象是否为可迭代对象

>>> from collections import Iterable
>>> isinstance('sakura',Iterable)
True
>>> isinstance(20,Iterable)
False

列表生成式

顾名思义就是用来创建列表的生成式

Python中可使用如下生成式简洁地生成列表[1,4,9,16,25,36,49,64,81,100],并且可以加上条件生成指定的列表,还可以使用两层for循环,生成全排列。

>>> [x*x for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
>>> [x*x for x in range(10) if x % 2==0]
[0, 4, 16, 36, 64]
>>> [x+y for x in 'abc' for y in '123']
['a1', 'a2', 'a3', 'b1', 'b2', 'b3', 'c1', 'c2', 'c3']

生成器

我对于生成器的理解:它是不断生成计算下一值的一个可迭代的对象

这里借用在学习Python生成器时引入的一个问题。
前面介绍了列表生成式,那我们就可以通过列表生成式创建一个列表,但是受到内存限制,列表的容量是有限的。如果我们创建一个100万的元素的列表,不仅会占很大存储空间,要是我们仅仅只访问前面几个元素,那么后面大部分空间都浪费了!这里的问题在于,列表生成式会一次性计算出元素值。
为了解决这个问题,我们引入生成器,生成器(generator)可可以一边循环一边计算后面的元素值。

扫描二维码关注公众号,回复: 1476993 查看本文章

创建生成器的方法有多种,下面介绍两种创建生成器的方法。

生成器推导式

类似于列表生成式,将列表生成式的“[]”换成“()”,即创建了一个generator。

>>> a_gen=(x*x for x in  range(3))
>>> a_gen
<generator object <genexpr> at 0x000001E862DFC830>

访问生成器中的元素,可以通过next()函数。next()函数获得generator的下一个返回值直到遇见StopIteration的错误。

>>> next(a_gen)
0
>>> next(a_gen)
1
>>> next(a_gen)
4
>>> next(a_gen)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

generator是可迭代的对象,所以可以通过for循环进行访问。
Python中的for循环会自动调用迭代器和next()方法、自动捕获StopIteration异常并结束循环。

>>> a_gen=(x*x for x in  range(3))
>>> for item in a_gen:
...     print(item)
...
0
1
4
>>> for item in a_gen:
...     print(item)
...
>>>

包含yield的生成器函数

当生成器中元素值的推算算法非常复杂时,用类似于列表生成式的for循环无法解决时,还可以用函数实现generator。

定义generator的另一种方法:如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator。
当执行到函数中的yield语句时,函数将被暂时挂起,保留其的局部变量等数据,然后等下次调用时,继续从挂起的位置执行下去。

使用next()方法访问生成器

>>> def fun_gen():
...     print('generator starts!...')
...     yield print('first step,return')
...     yield print('back,second step')
...
>>> a=fun_gen()
>>> next(a)
generator starts!...
first step,return
>>> next(a)
back,second step
>>> next(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

使用for自动调用next()方法

>>> for i in fun_gen():
...     print('this is for')
...
generator starts!...
first step,return
this is for
back,second step
this is for

使用生成器生成斐波那契数列

>>> def fibs():
...     a=0
...     b=1
...     while True:
...          a,b=b,a+b
...          yield a
...
>>> for each in fibs():
...     if each > 300:
...         break
...     print(each,end='、')
...
1123581321345589144233

迭代器

Python中可直接用于for循环地数据类型有以下几种:

  • 集合数据类型:如list,tuple,dict,set,str等
  • generator,包括生成器推导式创建的生成器和带yield的generator function

这些可以直接用于for循环地对象统称为可迭代对象:Iterable。
可以用isinstance()判断一个对象是否是Iterable对象

>>> from collections import Iterable
>>> isinstance('sakura',Iterable)
True

能被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator
可以使用isinstance()判断一个对象是否是Iterator对象

>>> from collections import Iterator
>>> isinstance((x*x for x in range(5)),Iterator)
True
>>> from collections import Iterable
>>> isinstance((x*x for x in range(5)),Iterable)
True

上面讲到的生成器不但可以作用于for循环,也可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值。所以生成器是可迭代对象也是迭代器的一种实现。

生成器都是Iterator对象,但是list、dict、str只是Iterable对象,不是Iterator对象。

>>> from collections import Iterator
>>> isinstance('123',Iterator)
False

迭代器的实现

迭代器的实现需要一个完整的类。python提供了两个内置函数(IBF) iter() next()来实现。
在类中:
__iter__()返回迭代器本身
__next__()决定迭代器的迭代规则
实现了这两个方法的类就是迭代器

例如斐波那契数列的迭代器

class Fibs:
    def __init__(self,n=10):
        self.a = 0
        self.b = 1
        self.n = n

    def __iter__(self):
        return self

    def __next__(self):
        self.a ,self.b = self.b,self.a+self.b
        if self.a > self.n:             #防止无限打印
            raise StopIteration
        return self.a
>>> test=Fibs(5)
>>> for item in test:
    print(item)


1
1
2
3
5
>>> from collections import Iterator
>>> isinstance(test,Iterator)
True

猜你喜欢

转载自blog.csdn.net/renzhadebenyuan/article/details/80172126
今日推荐