真锋
永远保持一颗学习和专注的心
嵌入式视觉
Python3高级特性

本文为学习笔记,参考资料《廖雪峰-Python3教程》

目录

  • 切片
  • 迭代
  • 列表生成式
  • 生成器
  • 迭代器

掌握了 Python 的数据类型、语句和函数,基本上就可以编写出很多有用的程序了。但是我们还需要掌握Python的一些高级特性,精简代码。一行代码能实现的功能,绝不写5行代码。Python的高级特性:切片,迭代,列表生成式,生成器,迭代器

切片

对这种经常取指定索引范围的操作,用循环十分繁琐,因此, Python 提供了切片(Slice)操作符,能大大简化这种操作。取前 3 个元素,用一行代码就可以完成切片:

https://www.armcvai.com/wp-content/uploads/2019/08/image-41.png
切片实例
https://www.armcvai.com/wp-content/uploads/2019/08/切片代码.png
切片代码

注意:tuple 也是一种 list,唯一区别是 tuple 不可变。因此, tuple 也可以用切片操作,只是操作的结果仍是 tuple:

迭代

如果给定一个 list 或 tuple,我们可以通过 for 循环来遍历这个 list 或tuple,这种遍历我们称为迭代(Iteration),迭代时 Python 最强大的功能之一,是访问集合元素的一种方式。list 这种数据类型虽然有下标,但很多其他数据类型是没有下标的,但是,只要是可迭代对象,无论有无下标,都可以迭代,比如 dict 就可以迭代: 

https://www.armcvai.com/wp-content/uploads/2019/08/迭代实例.png
迭代实例

因为 dict 的存储不是按照 list 的方式顺序排列,所以,迭代出的结果顺序很可能不一样(key 是无序的)。默认情况下, dict 迭代的是 key。

  • 如果要迭代 value,可以用 for value dict.values()
  • 如果要同时迭代 key 和 value,可以用 for k, v in dict.items()
https://www.armcvai.com/wp-content/uploads/2019/08/遍历dict的key和value.png
dict 迭代 key 和 value

想要使用 dict 时,Key 是有序的,可以用 OrderedDict,如下:

from collections import OrderedDict
od = OrderedDict()
od['z'] = 1
od['y'] = 2
od['x'] = 3
list(od.keys())  # 按照插入的 Key 的顺序返回['z', 'y', 'x']

字符串也是可迭代对象,因此,也可以作用于 for 循环: 

https://www.armcvai.com/wp-content/uploads/2019/08/迭代字符串.png
迭代字符串

所以,当我们使用 for 循环时,只要作用于一个可迭代对象, for 循环就可以正常运行,而我们不太关心该对象究竟是 list 还是其他数据类型。通过 collections 模块的 Iterable 类型判断一个对象是否可迭代。list,tuple,dict,字符串对象都是可迭代对象。 

注意:Python 内置的 enumerate 函数可以把一个 list 变成索引-元素对,这样就可以在 for 循环中迭代索引和列表元素本身。例子如下:

https://www.armcvai.com/wp-content/uploads/2019/08/enumerate函数迭代.png
enumerate函数迭代

列表生成式

列表生成式即 List Comprehensions,是 Python 内置的非常简单却强大的可以用来创建 list 的生成式。写列表生成式时,把要生成的元素 x * x 放到前面,后面跟 for 循环,就可以把 list 创建出来,十分有用,我在实际项目中经常大量应用列表生成式简化代码。

https://www.armcvai.com/wp-content/uploads/2019/08/列表生成式代码-1.png
列表生成式代码

运用列表生成式,可以写出非常简洁的代码。例如,列出当前目录下的所有文件和目录名,可以通过一行代码实现: 

https://www.armcvai.com/wp-content/uploads/2019/08/列出当前目录下所有文件和目录-1.png
列出当前目录下所有文件和目录

也可把一个 list 中所有的字符串变成小写,代码如下所示: 

https://www.armcvai.com/wp-content/uploads/2019/08/列表生成式实例2-1.png
列表生成式实例2

运用列表生成式,可以快速生成 list,可以通过一个 list 推导出另一个 list,而代码却十分简洁**。 

https://www.armcvai.com/wp-content/uploads/2019/08/通过一个list生成一个新list-1.png
通过一个list生成一个新list

迭代器

先了解下什么是可迭代对象(Iterable)。我们知道,可以直接作用于 for 循环的数据类型有以下几种:

  • 一类是集合数据类型,如 list、 tuple、 dict、 set、 str 等;
  • 一类是 generator,包括生成器和带 yield 的 generator function。

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

  • 迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
  • 迭代器有两个基本的方法:iter() 和 next()
  • 字符串,列表或元组对象都可用于创建迭代器
>>> list=[1,2,3,4]
>>> it = iter(list) # 创建迭代器对象
>>> print (next(it)) # 输出迭代器的下一个元素
1
>>> print (next(it))
2

可以使用 isinstance() 判断一个对象是否是 Iterable 对象: 

https://www.armcvai.com/wp-content/uploads/2019/08/判断对象是否是-Iterable对象-1.png
判断对象是否是 Iterable对象

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

Iterable 变成 Iterator 可以使用 iter()函数:

为什么 list、 dict、 str 等数据类型不是 Iterator?

这是因为 PythonIterator 对象表示的是一个数据流, 迭代器 Iterator 对象可以被 next() 函数调用并不断返回下一个数据,直到没有数据时抛出 StopIteration 错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过 next() 函数实现按需计算下一个数据,所以 Iterator 的计算是惰性的,只有在需要返回下一个数据时它才会计算。

Iterator 甚至可以表示一个无限大的数据流,例如全体自然数。而使用 list 是永远不可能存储全体自然数的 。

小结

  • 凡是可作用于 for 循环的对象都是 Iterable 类型;
  • 凡是可作用于 next() 函数的对象都是 Iterator 类型,它们表示一个惰性计算的序列;
  • 集合数据类型如 list、 dict、 str 等是 Iterable 但不是 Iterator,不过可以通过 iter()函数获得一个 Iterator 对象。

生成器(Generator)

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含 100 万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的 list,从而节省大量的空间。在 Python 中,这种一边循环一边计算的机制,称为生成器: generator
要创建一个 generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的 [] 改成 (),就创建了一个 generator:

 g = (x*x for x in np.arange(10))

创建列表生成式 L 和 迭代器 g 的区别仅在于最外层的 [](), L 是一个 list,而 g 是一个generator。除了用列表生成式的 for 循环方式创建 generator,还可以使用函数来实现,在 Python 中,使用了 yield 的函数被称为生成器(generator)。变成 generator 的函数,在每次调用 next()的时候执行,遇到 yield 语句返回,再次执行时从上次返回的 yield 语句处继续执行。如用 yield 实现斐波那契数列生成器函数:

斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到。

#!/usr/bin/python3
import sys
def fibonacci(n): # 生成器函数 - 斐波那契
    a, b, counter = 0, 1, 0
    while True:
        if (counter > n): 
            return
        yield a
        a, b = b, a + b
        counter += 1
f = fibonacci(10) # f 是一个迭代器,由生成器返回生成

while True:
    try:
        print (next(f), end=" ")
    except StopIteration:
        sys.exit()

程序输出如下:

0 1 1 2 3 5 8 13 21 34 55

小结

generator 是非常强大的工具,在 Python 中,可以简单地把列表生成式改成 generator,也可以通过函数实现复杂逻辑的 generator。

参考资料

《廖雪峰-Python3教程》 
菜鸟教程-Python3

赞赏

发表评论

textsms
account_circle
email

嵌入式视觉

Python3高级特性
本文为学习笔记,参考资料《廖雪峰-Python3教程》 目录 切片迭代列表生成式生成器迭代器 掌握了 Python 的数据类型、语句和函数,基本上就可以编写出很多有用的程序了…
扫描二维码继续阅读
2019-08-29
标签
2019年十二月
« 9月    
 1
2345678
9101112131415
16171819202122
23242526272829
3031  
近期文章