python高级编程

推导式

  推导式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
2
A = {"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
2
A = ["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
2
A = ["apple", "orange", "banana", "pear"]
A = {len(s) for s in A}

  程序输出:

1
[5, 6, 6, 4]

可迭代对象

定义

  可迭代对象:实现了__iter__()方法的对象都是可迭代对象。如果没有实现__iter__而实现了__getitem__方法,并且其参数是从零开始的索引,这种对象,如序列,也是可迭代的。
data
  迭代器:实现了__iter____next__()方法的对象都是迭代器。
  由定义可知,除了内置的序列和字典之外,我们还可以自己定义可迭代对象。

iter()

  该方法返回的是当前对象的迭代器类的实例。因为可迭代对象与迭代器都要实现这个方法,因此有以下两种写法。

  1. 用于可迭代对象类的写法,返回该可迭代对象的迭代器类的实例。
  2. 用于迭代器类的写法,直接返回self(即自己本身),表示自身即是自己的迭代器。

next()

  表示获取迭代器对象中下一个值。

创建可迭代对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from collections import Iterable


# 自定义可迭代对象
class MyList(object):
def __init__(self):
# 定义一个空列表,保存用户添加的数据
self.my_list = list()

# 在列表中添加元素
def append_data(self, data):
self.my_list.append(data)

# 在类里面提供__iter__方法,使该对象是可迭代对象
def __iter__(self):
pass

# 通过自定义可迭代类型创建自定义可迭代对象
my_iterable = MyList()

# 查看my_iterable是不是指定类型:Iterable
result = isinstance(my_iterable, Iterable)
print(result)

  在创建的类中,由于定义了__iter__()方法,即使该方法为空,但已经满足了可迭代对象的定义,所以用isinstance()检测是否为可迭代对象时,输出的结果为true
  可迭代对象的本质是通过迭代器帮助可迭代对象依次迭代对象中的每一个数据,所以真正完成获取数据的操作是通过迭代器完成的。

创建迭代器

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class MyList(object): 
def __init__(self):
self.my_list = list()

def append_data(self, data):
self.my_list.append(data)

# 使用__iter__()的第一种写法
def __iter__(self):
my_iterator = MyIterator(self.my_list)
return my_iterator


# 自定义迭代器类
class MyIterator(object):
def __init__(self, current_list):
# 保存外界传入过来的数据对象
self.current_list = current_list
# 记录获取数据的下标
self.current_index = 0

# 使用__iter__()的第二种写法
def __iter__(self):
return self

# 使用__next__方法获取指定对象中的数据
def __next__(self):
# 判断下标是否越界
if self.current_index < len(self.current_list):
# 根据下标获取数据对象中的指定数据
value = self.current_list[self.current_index]
# 获取数据成功对下标加上1
self.current_index += 1
return value
else:
# 代码执行到此说明下标越界,停止取值操作,抛出停止迭代异常
raise StopIteration


if __name__ == "__main__":
# 通过自定义可迭代类创建出自定义可迭代对象,添加数据
my_iterable = MyList()
my_iterable.append_data(1)
my_iterable.append_data(2)

for value in my_iterable:
print(value, end=',')

  输出结果为:1,2。迭代器的标配就是__iter____next__方法,每个迭代器都有,这种方法是自从它被创建出来的时候就有。真正的迭代是由__next__来执行的,也就是__next__每次从迭代器中取出一个元素来操作,直到所有的元素被取完。
  当然也可以用python内置的迭代器函数生成迭代器。iter()函数表示获取可迭代对象的迭代器,会调用可迭代对象身上的__iter__方法,next()函数表示获取迭代器对象中下一个值,会调用迭代器对象身上的__next__方法。例:

1
2
3
4
5
6
7
8
9
10
11
if __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()函数。

谢谢老板!