Python3 高级特性
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python3 高级特性相关的知识,希望对你有一定的参考价值。
本文为学习笔记,参考资料《廖雪峰-Python3教程》
目录
- 切片
- 迭代
- 列表生成式
- 生成器
- 迭代器
掌握了 Python
的数据类型、语句和函数,基本上就可以编写出很多有用的程序了。但是我们还需要掌握 Python 的一些高级特性,精简代码。一行代码能实现的功能,绝不写 5 行代码。Python 的高级特性:切片,迭代,列表生成式,生成器,迭代器。
切片
对这种经常取指定索引范围的操作,用循环十分繁琐,因此, Python 提供了切片(Slice)
操作符,能大大简化这种操作。取前 3 个元素,用一行代码就可以完成切片:
注意:tuple
也是一种 list
,唯一区别是 tuple 不可变。因此, tuple 也可以用切片操作,只是操作的结果仍是 tuple:
迭代
只要是可迭代对象,都可以用切片、索引、enumarate
等操作。
如果给定一个 list
或 tuple
,我们可以通过 for 循环来遍历这个 list 或tuple,这种遍历我们称为迭代(Iteration)
,迭代时 Python 最强大的功能之一,是访问集合元素的一种方式。list 这种数据类型虽然有下标,但很多其他数据类型是没有下标的,但是,只要是可迭代对象,无论有无下标,都可以迭代,比如 dict
就可以迭代:
因为 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 循环:
所以,当我们使用 for 循环时,只要作用于一个可迭代对象, for 循环就可以正常运行,而我们不太关心该对象究竟是 list 还是其他数据类型。可通过 collections
模块的 Iterable
类型判断一个对象是否可迭代。list,tuple,dict,字符串对象都是可迭代对象。注意:Python 内置的 enumerate
函数可以把一个 list 变成索引-元素对
,这样就可以在 for 循环中迭代索引和列表元素本身。例子如下:
列表生成式
列表生成式
即 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 创建出来,代码如下。
对于两层 for 循环的情况左边的循环是外层循环,右边的循环是内层循环,三层和三层以上的循环也等效,不过实际项目中很少用到。运用列表生成式,可以写出非常简洁的代码。例如,把一个 list 中所有的字符串变成小写,可以通过一行代码实现:
Python列表生成式配合 if else
-
[i for i in range(k) if condition]
:此时 if
起条件判断作用,满足条件的,将被返回成为最终生成的列表的一员。 -
[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]
迭代器
先了解下什么是可迭代对象(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
对象:
可以被 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。
参考资料
- 《廖雪峰-Python3教程》
- 菜鸟教程-Python3
以上是关于Python3 高级特性的主要内容,如果未能解决你的问题,请参考以下文章