在python中提供了对有序可迭代对象(String、Tuple、List)的高级功能如切片、迭代和生成式等功能,便于开发者摒弃繁琐的循环结构编写方式。
1.切片、迭代、生成式
- 切片:Python中为可迭代对象中的数据提供了正向索引和反向索引功能,通过索引和限定步长可以快捷的切出想要的部分
(其中end值取不到)
有序可迭代对象[<start>:<end><:steps>]
stringA = "stringA"
listA = [1,2,3,4]
tupleA = (5,6,7,8,9,10)
print(stringA[:],listA[1:2],tupleA[1:-2],tupleA[1::2])
结果是:
>stringA [2] (6, 7, 8) (6, 8, 10)
- 迭代:Python中通过for in 的语句来迭代有序可迭代对象(List、String、Tupel)及及生成器
for i in {"name":"Tony","ages":19}.items():
print(i)
- 生成式:以简洁高效的方式重构及调整List、Tuple、Dict,不需要for in 的多行结构
listA = [1,2,3,4]
tupleA = (5,6,7,8,9,10)
dictFex = {"a":2,"b":3}
print([i*i for i in listA])
print(tuple([i*i for i in tupleA]))
print({b:a for a,b in dictFex.items()})
# 添加过滤器选取需要操作的对象,在for in 后面加上if过滤
print([i*i for i in listA if i % 2 == 0])
# 多层嵌套
print([m + n for m in 'ABC' for n in 'XYZ'])
# 选择式执行,在for in前面加上 操作1 if 判断1 else 操作2
print([x if x % 2 == 0 else x*x for x in tupleA])
结果是:
>[1, 4, 9, 16]
>(25, 36, 49, 64, 81, 100)
>{2: 'a', 3: 'b'}
>[4, 16]
>['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
>[25, 6, 49, 8, 81, 10]
2.迭代器
由于计算机内存有限,在程序语言设计的时候会考虑大数据集的惰性获取机制即迭代器模式,其实现了让用户通过特定的接口巡防容器内的每个元素。在python语言的设计中也构造了类似的机制,设计了迭代器可以陆续获取元素的读取机制。
除了上面提到的有序可迭代对象外还有如set、dict这些集合数据类型也可通过for
来循环调用的对象称为可迭代对象Iterable
。可迭代对象被for
调用的机理是:可迭代对象内部实现了_iter_
函数,在调用后可以用_iter_
函数构造并返回一个迭代器Iterrator
,迭代器实现了_next_
函数来调用陆续输出下一个元素,但没有元素时会抛出StopIteration异常(迭代器被for
调用时也是一样调用_iter_
函数,此时是直接返回自身,之后依旧是以该返回的迭代器),构造迭代器最典型的应用便是生成器。
简而言之,迭代器是一种惰性数据访问机制用于减轻程序运行的内存消耗。可迭代对象被for调用时需要先调用内部的_iter_函数构造出一个实现_next_函数的迭代器,基于这个迭代器的_next_函数便可以陆续调取出下一个元素,当没有元素时便会抛出StopIteration异常。
Python有内嵌函数iter()可以将可迭代对象装换成迭代器,而内嵌函数next()可以调用迭代器的next函数来陆续获取下一个元素。
from collections.abc import Iterable
iterableA = [1,2,3]
print(isinstance(iterableA, Iterable))
iteratorA = iter(iterableA)
print(type(iteratorA))
print(type(iter(set(iterableA))))
print(next(iteratorA))
结果是:
>True
><class 'list_iterator'>
><class 'set_iterator'>
>1
3.生成器
当存在一些数据不需要一次性存储在内存中并且具有一定的推算规则时,可以利用生成器陆续导出而不必占用大量内存。简单生成器可以通过利用生成式来产生,当for in 没办法表达推理逻辑时,可以构造生成器函数。
# 生成式构造生成器
generator = (x*x for x in range(5))
print(generator)
for i in generator:
print(i,end=' ')
# 构造生成器函数,返回一个函数句柄,通过next函数调用该句柄,将循环执行到yield字段
# 打印斐波拉契数列
def fibonacci(jie):
n, b, c = 0,0,1
while n < jie:
yield c
b, c = c, b + c
n += 1
return 'done'
generatorFunc = fibonacci(5)
# 通过for in对存在对象循环调用,当往后不再有yield便不会继续执行故不会走到return
for i in generatorFunc:
print(i,end = ' ')
# 用while一直调用到return产生StopIteration错误返回值在value中
while True:
try:
n = next(generatorFunc)
print(n,end = ' ')
except StopIteration as e:
print(e.value)
break
# 产生正整数
def number():
firstNum = 0
while True:
firstNum += 1
yield firstNum
return 'done'
funcdo = number()
print(next(funcdo))
# 杨辉三角
def triangles():
result = [1]
while True: # 这是让每一调用都能进入到循环中
yield result # 这是每次调用的时候的打印结果
result = [1] + [x+y for x, y in zip(result[:-1], result[1:])] + [1]
结果为:
><generator object <genexpr> at 0x00000225A0181740>
>0 1 4 9 16
>1 1 2 3 5
>1 1 2 3 5 done
注意
生成器函数和普通的函数不一样,不是直接执行到return结束,而是在每一次next调用时都会执行到yield字段并返回该字段后面的变量值,下一次调用next的时候将从上一次yield位置往后执行再次遇到yield字段返回,因此往往在生成器函数中都会存在循环结构来循环操作。当程序执行到return时,生成器函数将会产生StopIteration错误,其value包含返回值。
`