廖雪峰Python教程阅读笔记——3. 高级特性

来源:互联网 发布:欧洲历史书籍推荐知乎 编辑:程序博客网 时间:2024/06/05 19:25

3 高级特性

3.1 切片

切片使用方法list[start,end,step]

  • start:起始位置

  • end:终止位置,但不包括end下标的值

  • step:步进

取一个list或tuple的部分元素是常见的现象,比如,一个list如下:

>>>L=['Mac','Iphone','Nokia','Huawei','OPPO']

取前三个数:

>>>L[0:3]['Mac', 'Iphone', 'Nokia']

上述就是切片操作,L[0:3]表示从索引0开始,直到索引3结束,但不包含索引3位置的值。

当索引为0时,可以省略L[:3]

列出所有的值:L[:]

既然索引可以从-1开始,类似,取倒数的值也是可以的:

>>> L[-3:-1]['Nokia', 'Huawei']

记住:倒数第一个数的索引是-1

tuple也是一种list,也可以使用切片,操作的结果也是个tuple

3.2 迭代

如果给定一个listtuple,我们可以通过for循环遍历这个listtuple,这种遍历我们称之为迭代(Iteration)。

在Python中,迭代是通过for...in...来完成的。list虽然这种类型有下标,但是也有很多数据类型没有下标,比如dict,但是只要是可迭代对象,无论有无下标,都可以迭代。

那么,如何判断一个对象是可迭代对象呢?方法是通过Collections模块的Iterable类型判断:

>>>from collections import Iterable>>>isinstance('abc', Iterable)  #str是否可迭代True>>> isinstance(222,Iterable)  #整数不可迭代False

如果要对list实现类似java那样的下标循环,可以使用enumerate函数,把list变成索引-元素对。这样就可以使用for循环中同时迭代索引和元素本身:

>>>for i,value in enumerate(['Mac','Iphone','Nokia','Huawei','OPPO']):... print(i,value)0 Mac1 Iphone2 Nokia3 Huawei4 OPPO

上面的for循环,可以同时引用两个变量,在Python中是很常见的:

>>>for x,y in [(1,'a'),(2,'b'),(3,'c')]:...print(x,y)...1 'a'2 'b'3 'c'

3.3 列表生成式

列表生成式即List Comprehensions,是Python内置的非常简单但强大的可以创建List的生成式。

举例:要生成list [1,2,3,4,5,6,7,8],可以使用list(range(1,8))

>>> list(range(1,8))[1, 2, 3, 4, 5, 6, 7]

但是要生成[1x1,2x2,3x3,…,7x7],则需要for循环实现:

>>> L=[]>>> L[]>>> for x in range(1,8): L.append(x*x)...>>> L[1, 4, 9, 16, 25, 36, 49]

但是如此,代码比较繁琐。因此Python引入了列表生成式:

>>> [x*x for x in range(1,8)][1, 4, 9, 16, 25, 36, 49]

只需要一行代码,就可以实现。写列表生成式时,x*x要写在前面,后面跟for循环,就可以把列表创建出来。for循环后面还可以跟if判断,这样就可以筛选list

>>> [x*x for x in range(1,8) if x%2==0][4, 16, 36]

3.4 生成器

通过列表生成器,我们可以直接创建一个列表。但是,收到内存限制,列表容量是有限的。而且,创建一个包含100万个元素的数据,不仅占用内存很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面的元素占用的空间都白白浪费了。

如果列表元素可以按照某种算法计算出来,一边循环一边计算,在Python中,我们称之为生成器:gererator。

generator:

>>> L=[x*x for x in range(1,10)]>>> L[1, 4, 9, 16, 25, 36, 49, 64, 81]>>> g=(x*x for x in range(1,10))>>> g<generator object <genexpr> at 0x000001A73F646E60>>>> next(g)1>>> next(g)4

我们可以通过next(g)获取generator的下一个返回值。直到计算最后一个元素的值,如果没有更多的元素,会报StopIteration的错误。当我们创建一个generator后,一般不用next()函数计算下一个元素的值,而是用for循环。

斐波那契数列(Fibonacci),很难用generator生成器生成出来:

def fib(max):    n,a,b = 0,0,1    while n<=max:        print(b)        a,b = b,a+b        n = n + 1    return 'done'

上面的函数可以输出斐波那契数列的前N个数。可以看到,上面的函数跟generator很接近了。如果要把该函数改造成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 = n + 1    return 'done'

关键字yield:首先理解一下generator函数执行过程,该过程跟函数的执行流程不一样,函数的执行顺序,遇到return语句或者最后一行语句就返回。而generator的函数,在每次调用next()函数的时候执行,遇到yield语句返回,再次执行时,从上次返回的yield语句处继续执行。

3.5迭代器

可直接作用于for循环的有两大类:

  • 集合类数据类型,如listtupledictsetstr

  • generator

这些可以直接作用于for循环的对象统称为可迭代对象Iterable

可以使用isinstance()判断一个对象是否为Interable对象。

可以被next()函数调用不断返回下一个值的对象成为迭代器Iterator:与Iterable的区别。

可以使用isinstance()判断一个对象是否为Iterator对象。

生成器都是Iterator对象,但listdictstr虽然是Iterable,但是可以使用Iter()函数将Iterable转换为Iterator

>>> isinstance(iter([]),Iterator)True>>> isinstance(iter('abc'),Iterator)True>>>

listtupledict不是Iterator,是因为Python中,Iterator是一个数据流,Iterator对象可以被next()函数调用并返回下一个值,直到没有数据时,才会抛出StopIteration。可以把这个数据流看成是一个有序序列,但我们无法直到序列的长度,只能通过不断的next()函数实现按需计算下一个值,所以Iterator`的计算是惰性的。只需要在返回下一个元素的时候,才会计算。

Iterator可以是一个强大的数据流,比如:自然数。而list是永远不可能存储自然数的。

  • 小结:

    • 凡是可以作用于for循环的都是Iterable对象。

    • 凡是可以使用next()函数的都是Iterator类型,它表示一个惰性计算的序列。

    • 集合数据类型如listtupledictsetstrIterable的,不过可以通过Iter()函数转换为Iterator对象。

原创粉丝点击