一、切片(Slice)
在很多编程语言中,针对字符串提供了很多截取函数(i.e. substring),目的就是对字符串切片。python中没有针对字符串的截取函数,需要通过“切片”来完成。
取一个list或tuple的部分元素可以用切片
格式: 假定list或tuple组成的元素组名为m
m[起始值:终止值:步长]
说明:
a. 起始值如果是0,可以省略,但是中间的冒号(:)一定要带上
b. 起始值,终止值限定的是索引范围。
c. 如果从前面开始取数,那么索引时不包括索引[终止值],因为索引时下标从0开始。
d. 如果从后面开始取数,即倒数,如果m[-2:] 则取最后两个元素,如果m[-2:-1]则取倒数第二个元素,注意两者的区别。
e. 不管从前面开始或从后面开始取数,最终取的元素个数为都为终止值-起始值。
python支持m[-1]取倒数第一个元素,那么它同样支持倒数切片。
tuple也可以用切片操作,操作结果仍是tuple。
字符串也可以用切片操作,只是操作结果仍是字符串。字符串'xxx'也可以看成一种list,每个元素就是一个字符。
二、迭代
如果给定一个list或tuple,通过for循环来遍历这个list或tuple,这种遍历称为迭代。
可迭代对象:list, tuple,字典dict,字符串,生成器generator
1、如何判断一个对象是可迭代对象呢?方法:通过collections模块的Iterable类型判断;
格式: 下面代码为判断时书写格式,python中大小写敏感
1 from collections import Iterable 2 print(isinstance('abd',Iterable)) #字符串是否可迭代 3 4 print(isinstance([1,2,4],Iterable)) #list是否可迭代 5 6 print(isinstance(123,Iterable)) #整数是否可迭代
下面为在命令交互行测试代码:
2、dict迭代
默认情况下,dict迭代的是key,如果要迭代value,可以用for value in d.values(),如果要同时迭代key和value,可以用for k, v in d.items().
下面是使用代码:
1 d={'a':1,'b':2,'c':3} #这是一个dict 2 for key in d: # 遍历key,由于默认是key,所以 in d,如果默认不是key,就需要写成 in d.keys
3 print(key) 4 for value in d.values(): #遍历每一个值 5 print(value) 6 # 遍历每一个值,这个跟上面的效果是一样的,只不过上面是value,这个是v,这都可以, 7 # for 和in 中间使用value,那么print中也要用value,不能使用v,要保持一致 8 for v in d.values(): 9 print(v) 10 for k,v in d.items(): #遍历key和值 11 print(k,v)
字符串也是可迭代对象,因此,也可作用于for 循环:
1 for ch in 'abdf': 2 print(ch)
python内置的enumerate函数可以把一个list变成索引-元素对,这样可以在for循环中同时迭代索引和元素本身:
1 #python内置的enumerate函数可以把一个list变成索引-元素对, 2 #这样就可以在for循环中同时迭代索引和元素本身 3 for i, value in enumerate(['a','b','c']): 4 print(i,value)
python中for循环里,同时引用两个变量是很常见的,代码如下:
1 for x, y in [(1,1),(2,3),(3,9)]: 2 print(x,y)
下面使用next也可以遍历list中每一个元素:
1 it=iter([1,2,3,4,5,6]) 2 print(next(it)) 3 print(next(it)) 4 print(next(it)) 5 print(next(it)) 6 print(next(it))
在命令交互行模式下测试:
三、列表生成式
是Python内置的可以用来创建list的生成式。
使用方法: 前面一部分是对元素进行的操作,最后面一部分是对元素进行判断
1 print([x*x for x in [1,2,3,4,5]]) 2 3 print([x*x for x in range(1,11)]) 4 5 print([x*x for x in range(1,11) if x % 2 == 0 ]) 6 7 print([m+n for m in 'ABC' for n in 'XYZ'])
实例:列出当前目录下的所有文件和目录名
1 import os # 导入os模块 2 print([d for d in os.listdir('.')])
实例:把list中所有的字符串变成小写
1 L=['hello','world','IBM','Apple'] 2 print([s.lower() for s in L])
注意:s.lower()中的括号一定要带上,否则会报错
列表生成式练习题目:把一个list中的所有字符串变成小写。
思路: 如果list中既包含字符串,又包含数字,由于非字符串类型没有Lower()方法,所以列表生成式会报错:
1 L1=['Hello','World',18,'Apple'] 2 print([s.lower() for s in L1 ])
报错信息:
可以使用isinstance()函数判断一个变量是不是字符串,下面为修改后并测试成功的代码:
1 L1=['Hello','World',18,'Apple'] 2 print([s.lower() for s in L1 if isinstance(s,str) == True])
四、生成器generator
如果列表元素可以按照某种算法推算出来,那我们因此可以在循环的过程中不断推算出后续的元素,这样就不必创建完整的list,从而节省大量的空间。
在Python中,这种一边循环 一边计算的机制,称为生成器:generator。
创建generator的方法
(1)把一个列表生成式的中括号[ ]改成小括号( ),就创建了一个generator。
1 #这个是创建list 2 L=[x*x for x in range(10)] 3 print(L) 4 #这个是创建生成器generator,使用的是小括号 5 g=(x*x for x in range(10)) 6 print(g)
(2)创建generator方法:yield关键字
generator保存的是算法,如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。
如果一个函数定义中包含了yield关键字,那么这个函数就不再是一个普通函数,而是一个generator。
注意:这里最难理解的是,generator和函数的执行流程不一样。
函数是顺序执行,遇到return语句或者最后一行函数语句就返回。
而generator函数,在每次调用next( )的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
生成器generator中如何访问每个元素?
方法一: NEXT()函数
方法二:For循环
因为通过Next( )函数太繁琐了,而且generator也是可迭代对象(Iterable),所以可以使用for循环来访问每个元素:
1 g=(x*x for x in range(10)) 2 for n in g: 3 print(n)
生成器generator的小结:
1、使用类似列表生成式创建generator时,注意是小括号。
2、使用函数创建generator时,函数定义中要有yield关键字。
3、generator保存的是算法。
4、访问generator中的每个元素:next( )或for循环
5、generator是可迭代对象Iterable
6、每次调用next( g ),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多元素时,抛出StopIteration的错误。
当创建一个generator后,基本上不会调用next( ),而是通过for循环来迭代它,并且不需要关心StopIteration的错误。
五、迭代器
可直接作用于for循环的数据类型有:
第一类是集合数据类型,如list, tuple, dict, set, str等。
第二类是generator, 包括生成器和带 yield 的generator function.
可直接作用于for循环的对象统称为可迭代对象:Iterable.
可被next( )函数调用并不断返回下一个值的对象称为迭代器:Iterator.
使用isinstance( )函数来判断一个对象是否是Iterable对象或Iterator对象。
生成器都是Iterator对象,但list, dict, str虽然是Iterable,却不是Iterator。可以使用iter( )函数把list, dict, str等Iterable转换成Iterator。
为什么list, dict, str等数据类型不是Iterator?
这是因为Iterator对象表示的是一个数据流,Iterator对象可以被next( )函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能通过next( )函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。
Iterator甚至可以表示一个无限大的数据流,i.e. 全体自然数,而使用list是永远不可能存储全体自然数的。