切片
我们要获取一个list或者tuple里面的元素,我们一般是通过for循环来获取的,但是要获取指定索引范围内的元素,用for循环的话略显繁琐,不过,Python给我们提供了切片(Slice)操作符
l = [1, 2, 3, 4, 5]
print(l[1:4]) # [2, 3, 4]
print(l[-4:-1]) # [2, 3, 4]
print(l[2:]) # [3, 4, 5]
通过切片的方式获取的元素一般是包含头不包含尾
在Python中并没有提供像Java中对字符串进行截取的函数,不过,字符串可以通过切片来实现截取的功能
print("ABCDEFG"[2:5]) # CDE
迭代
我们之前通过for...in ..有对list和tuple进行循环,这种循环叫迭代(Iteration)。能够被迭代的对象,我们称之为迭代对象(Iterable),那么如何判断一个对象是否为Iterable了?还记得上篇文章有一个函数参数类型检查的吗?是的,就是通过isinstance函数来判断。
from collections import Iterable
print(isinstance("abc", Iterable)) # True
print(isinstance([], Iterable)) # True
print(isinstance((), Iterable)) # True
print(isinstance({}, Iterable)) # True
print(isinstance(123, Iterable)) # False
list的迭代比较简单,不过我们只能够获取元素,如果要获取list中元素的索引的话,需要借助enumerate函数;默认是从0开始的,当然也可以从自己指定数开始
l = ["手机", "电脑", "飞机", "火车"]
for index, value in enumerate(l):
print(index, value)
print("-----------------")
for index, value in enumerate(l, 1):
print(index, value)
打印结果:
0 手机
1 电脑
2 飞机
3 火车
-----------------
1 手机
2 电脑
3 飞机
4 火车
默认情况下,dict的迭代是key,我们也可以只迭代value,或者都迭代
d = {"1": "手机", "2": "电脑", "3": "飞机", "4": "火车"}
for key in d:
print(key)
print("-----------------")
for value in d.values():
print(value)
print("-----------------")
for key, value in d.items():
print(key, value)
打印结果如下:
3
4
2
1
-----------------
飞机
火车
电脑
手机
-----------------
3 飞机
4 火车
2 电脑
1 手机
列表生成式
通过list函数可以生成一个list列表,如:
# range(start,stop,间隔数),根据间隔数获取指定范围内的数,默认为0
print(list(range(1, 11))) # [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
若要生成[1x1, 2x2, 3x3, ..., 10x10],可以这样写:
print(list(x * x for x in range(1, 11))) # [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
若只需要生成偶数的平方,可以这样写:
print(list(x * x for x in range(1, 11) if x % 2 == 0)) # [4, 16, 36, 64, 100]
for循环嵌套
print(list(m + n for m in "AB" for n in "CD")) # ['AC', 'AD', 'BC', 'BD']
生成器(generator)
- 作用
生成器是用来在循环的过程中不断推算出后续的元素,这样就不必创建完整的list,从而节省大量的空间。
-
创建方式
-
把一个列表生成式的
[]
改成()
g = (x * x for x in range(1, 11, 2)) print(g) # <generator object <genexpr> at 0x102184990> # 通过next函数来获取元素 print(next(g)) # 1 print(next(g)) # 9 print(next(g)) # 25 print(next(g)) # 49 print(next(g)) # 81 print(next(g)) # StopIteration
当最后一个元素被计算出来后,再去计算下一个元素的话,会报一个StopIteration错误
-
在函数定义中包含yield关键字
def odd(): print("step 1") yield 1 print("step 2") yield 2 print("step 3") yield 3
获取元素:
g = odd() print(g) print(next(g)) print(next(g)) print(next(g))
打印结果如下:
<generator object odd at 0x100784990> step 1 1 step 2 2 step 3 3
从打印结果可以看出,当第一次通过next函数获取元素时,由于遇到了yield,所以此时函数的执行就会被中断,将yield设定的值返回给调用者;然后第二次调用开始,此时程序会从上次中断的位置重新开始,继续执行代码,若又遇到yield,又会被中断,后面的就依此类推
-
-
迭代生成器
上面从生成器中去获取元素都是通过一个一个去调用next函数,很显然,这种变态的做法,我们程序员是不可能去做的。我们一般是通过for、while循环来获取的。还是以上面的odd函数为例。
while True: try: r = next(g) print("g:", r) except StopIteration as e: print("Generator return value:", e.value) # 遇到StopIteration就退出循环 break # 打印结果如下: g: 1 g: 2 g: 3 Generator return value: None # 这里的try... except...类似于Java中的try...catch语句
迭代器(Iterator)
之前我们有学习到迭代对象,凡是可以被for循环的对象统称为可迭代对象(Iterable),当时是用isinstance函数来判断一个对象是否是可迭代对象。
可以被next函数调用并不断返回下一个值的对象称为迭代器(Iterator)。也可以用isinstance函数来判断哪些数据类型属于Iterator
from collections import Iterator
print(isinstance((x for x in range(1, 10)), Iterator)) # True
print(isinstance([], Iterator)) # False
print(isinstance({}, Iterator)) # False
print(isinstance("abc", Iterator)) # False
虽然list,dict,str不是Iterator,但可以通过iter函数来进行转换
print(isinstance(iter(()), Iterator)) # True
为什么list、dict、str等数据类型不是Iterator?
这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算
Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。
凡是可作用于for循环的对象都是Iterable类型;
凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。