推导式
推导式comprehensions
(又称解析式),是Python的一种独有特性。推导式是可以从一个数据序列构建另一个新的数据序列的结构体。
列表推导式
1 | [expression for item in iterable if condition] |
例:1
num = [num + 1 for num in range(0, 5) if num % 2 == 1]
程序输出:1
[2, 4]
字典推导式
1 | {key_expression:value_expression for expression in iterable if condition} |
例:1
2A = {"a": 1, "b": 2, "c": 3, "d": 4}
A = {v: k for k, v in A.items()}
程序输出:1
{1: 'a', 2: 'b', 3: 'c', 4: 'd'}
例:1
2A = ["apple", "orange", "banana", "pear"]
A = {key: value for key, value in enumerate(A) if value == "apple"}}
程序输出:1
{0: 'apple'}
集合推导式
1 | {expression for expression in iterable if condition} |
例:1
2A = ["apple", "orange", "banana", "pear"]
A = {len(s) for s in A}
程序输出:1
[5, 6, 6, 4]
可迭代对象
定义
可迭代对象:实现了__iter__()
方法的对象都是可迭代对象。如果没有实现__iter__
而实现了__getitem__
方法,并且其参数是从零开始的索引,这种对象,如序列,也是可迭代的。
迭代器:实现了__iter__
和__next__()
方法的对象都是迭代器。
由定义可知,除了内置的序列和字典之外,我们还可以自己定义可迭代对象。
iter()
该方法返回的是当前对象的迭代器类的实例。因为可迭代对象与迭代器都要实现这个方法,因此有以下两种写法。
- 用于可迭代对象类的写法,返回该可迭代对象的迭代器类的实例。
- 用于迭代器类的写法,直接返回self(即自己本身),表示自身即是自己的迭代器。
next()
表示获取迭代器对象中下一个值。
创建可迭代对象
1 | from collections import Iterable |
在创建的类中,由于定义了__iter__()
方法,即使该方法为空,但已经满足了可迭代对象
的定义,所以用isinstance()
检测是否为可迭代对象
时,输出的结果为true
。
可迭代对象
的本质是通过迭代器
帮助可迭代对象
依次迭代对象中的每一个数据,所以真正完成获取数据的操作是通过迭代器
完成的。
创建迭代器
1 | class MyList(object): |
输出结果为:1,2
。迭代器的标配就是__iter__
和__next__
方法,每个迭代器都有,这种方法是自从它被创建出来的时候就有。真正的迭代是由__next__
来执行的,也就是__next__
每次从迭代器中取出一个元素来操作,直到所有的元素被取完。
当然也可以用python内置的迭代器函数生成迭代器。iter()
函数表示获取可迭代对象的迭代器,会调用可迭代对象身上的__iter__
方法,next()
函数表示获取迭代器对象中下一个值,会调用迭代器对象身上的__next__
方法。例:1
2
3
4
5
6
7
8
9
10
11if __name__ == "__main__":
# 创建迭代器对象
it = iter([1, 2, 3, 4, 5])
while True:
try:
# 获得下一个值:
x = next(it)
print(x, end=',')
except StopIteration:
# 遇到StopIteration就退出循环
break
输出结果为:1,2,3,4,5
。首先使用iter()
使列表成为迭代器(列表是可迭代对象,但不是迭代器),然后一直调用next()
函数不停地获取迭代器里面的值。注意,一定要加异常处理,因为一旦获取不到迭代器里面的值就会报错。
迭代器应用
使用迭代器生成斐波那契数列。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30# 迭代器完成斐波那契数列
class Fibonacci(object):
def __init__(self, num):
# num:表示根据个数生成数列
self.num = num
# 保存斐波那契数列前两个值
self.first = 0
self.second = 1
# 记录生成斐波那契数列的下标
self.current_index = 0
def __iter__(self):
return self
def __next__(self):
if self.current_index < self.num:
result = self.first
self.first, self.second = self.second, self.first + self.second
# 生成数据完成以后对下标加上1
self.current_index += 1
return result
else:
# 表示数列生成完成
raise StopIteration
if __name__ == "__main__":
# 创建生成斐波那契数列的对象
fib = Fibonacci(5)
for i in fib:
print(i, end=',')
输出结果为0,1,1,2,3,
。使用迭代器可以节省空间,没有上限控制。迭代器不会把每次生成的值保存起来,只会根据你的算法生成一个值。即可以用多少创建多少,而且可以无限创建。
创建生成器
生成器属于轻装版的迭代器,但生成器仍然是迭代器,不过是改进的。可以实现一边循环一边计算。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17# 生成器完成斐波那契数列
def fibonacci(num):
# num:表示生成器根据个数创建指定个数的fibonacci数列
first = 0
second = 1
current_index = 0
# 循环判断条件是否成立,表示是否生成斐波那契数列
while current_index < num:
result = first
first, second = second, first + second
current_index += 1
yield result
if __name__ == "__main__":
generator = fibonacci(5)
for a in generator:
print(a, end=',')
输出结果为0,1,1,2,3,
。生成器函数的定义方式和普通函数几乎一样,只不过它有一个yield
语句。当函数执行到yield
的时候,该函数被挂起,等待下次被next()
激活。带有yield
的函数不再是一个普通函数,而是一个生成器generator
, yield
相当于return
返回一个值,并且记住这个返回的位置,下次迭代时,代码从yield
的下一条语句开始执行。
生成器相比较迭代器,更加简洁,且功能完全相同,相当于内置了next()
函数。