Python3 高级特性

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python3 高级特性相关的知识,希望对你有一定的参考价值。

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

目录

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

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

切片

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

Python3

Python3

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

迭代

只要是可迭代对象,都可以用切片、索引、enumarate 等操作

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

Python3

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

  • 如果要迭代 value,可以用 ​​for value dict.values()​​。
  • 如果要同时迭代 key 和 value,可以用 ​​for k, v in dict.items()​​​。
    想要使用 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 循环:

Python3

所以,当我们使用 for 循环时,只要作用于一个可迭代对象, for 循环就可以正常运行,而我们不太关心该对象究竟是 list 还是其他数据类型。可通过 ​​collections​​​ 模块的 ​​Iterable​​ 类型判断一个对象是否可迭代。list,tuple,dict,字符串对象都是可迭代对象。注意:Python 内置的 ​​enumerate​​​ 函数可以把一个 list 变成​​索引-元素对​​,这样就可以在 for 循环中迭代索引和列表元素本身。例子如下:

Python3

列表生成式

​列表生成式​​即 List Comprehensions,是 Python 内置的非常简单却强大的可以用来创建 list 的生成式,可以让代码更简洁好看。比如实际项目中,如果碰到需要改变列表(迭代器)元素值的情况,简单写法是用 for 循环遍历出元素,然后处理,但是当循环体的代码只有一行或者比较简单时,可以考虑用列表生成式的高级写法代替原先的简单写法,让代码更简洁。如以下代码可用列表生成式写法代替:

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

很明显,上述代码的循环太繁琐,而列表生成式则可以用一行语句代替循环生成上面的 list。写列表生成式时,我们把要生成的元素 x * x 放到前面,后面跟 for 循环,就可以把 list 创建出来,代码如下。

Python3

对于两层 for 循环的情况左边的循环是外层循环,右边的循环是内层循环,三层和三层以上的循环也等效,不过实际项目中很少用到。运用列表生成式,可以写出非常简洁的代码。例如,把一个 list 中所有的字符串变成小写,可以通过一行代码实现:

Python3

Python列表生成式配合 if else

  1. ​[i for i in range(k) if condition]​​​:此时 ​​if​​ 起条件判断作用,满足条件的,将被返回成为最终生成的列表的一员。
  2. ​[i if condition else exp for exp]​​​:此时 ​​if…else...​​ 是三元表达式写法,被用来赋值,满足条件的 if 以及 else 被用来生成最终的列表。

代码示例如下:

print([i for i in range(10) if i%2 == 0])
print([i if i == 0 else 100 for i in range(10)])

程序输出如下:

[0, 2, 4, 6, 8]
[0, 100, 100, 100, 100, 100, 100, 100, 100, 100]

列表生成式和和 zip 函数结合使用

语法:​​[expression for x, y in zip(list1, list2)]​​​, 列表 list1 和 list2 长度要相等,如果不相等,则按照小的列表长度来遍历元素。
示例代码如下:

import numpy as np
list1 = np.arange(0,51) # 创建序列数组
list2 = np.linspace(0, 100,51, dtype=int)
ret1 = [x1+y1 for x1,y1 in zip(list1, list2)] # 列表 list1 和 list2 长度相等
print(ret1, len(ret1))

程序运行结果如下:

[0, 3, 6, 9, 12, 15, 18, 21, 24, 27, 30, 33, 36, 39, 42, 45, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 99, 102, 105, 108, 111, 114, 117, 120, 123, 126, 129, 132, 135, 138, 141, 144, 147, 150] 51

小结

运用列表生成式,可以快速生成 list,可以通过一个 list 推导出另一个 list,而代码却十分简洁。 在一个列表生成式中,​​for​​​ 前面的 ​​...if ... else...​​​ 是三元表达式写法,而 ​​for​​​ 后面的 ​​if​​​ 是过滤条件,不能带 ​​else​​​。注意:列表生成式只能判断最最基础的 if else 语句,不适用于 ​​elif​​ 语句。

>>> [x for x in range(1, 11) if x % 2 == 0]
[2, 4, 6, 8, 10]
>>> [x if x % 2 == 0 else -x for x in range(1, 11)]
[-1, 2, -3, 4, -5, 6, -7, 8, -9, 10]

Python3

迭代器

先了解下什么是可迭代对象(​​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​​ 对象:

Python3

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

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

这是因为 ​​Python​​​ 的 ​​Iterator​​ 对象表示的是一个数据流, 迭代器 ​​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),除第一个和第二个数外,任意一个数都可由前两个数相加得到。

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。

参考资料

  1. 《廖雪峰-Python3教程》
  2. 菜鸟教程-Python3

以上是关于Python3 高级特性的主要内容,如果未能解决你的问题,请参考以下文章

python3的学习之路八高级特性

Python3 高级特性

惰性函数——JS高级

RabbitMQ学习(下)——发布确认高级幂等性优先级惰性和RabbitMQ集群

Python高级特性

Python高级特性