一. 切片
对list或者tuple取指定索引范围的元素,可以通过切片操作
1. 取前n个元素:L[0:n]
L = ['A','B','C','D','E'] print(L[0:3]) # ['A', 'B', 'C']
2. 如果第一个索引是0,还可以省略:L[:n]
L = ['A','B','C','D','E'] print(L[:3]) # ['A', 'B', 'C']
3. 倒数切片:L[:-n]
L = ['A','B','C','D','E'] print(L[-3]) # C print(L[:-3]) # ['A', 'B'] print(L[-3:]) # ['C', 'D', 'E']
4. 前n个数,每m取一个:L[:n:m]
L = list(range(100)) print(L[:10]) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] print(L[:10:2]) # [0, 2, 4, 6, 8]
5. 所有数,每m个取一个:L[::m]
L = list(range(50)) print(L[::5]) # [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]
6. 复制一个list:L[:]
L = ['A','B','C','D','E'] M = L[:] print(M) # ['A', 'B', 'C', 'D', 'E'] L[2] = '1' print(L) # ['A', 'B', '1', 'D', 'E'] print(M) # ['A', 'B', 'C', 'D', 'E']
7. 取n~m范围内的数:L[n:m+1]
L = list(range(50)) n = 10 m = 20 print(L[n:m]) #[10, 11, 12, 13, 14, 15, 16, 17, 18, 19] print(L[n:m+1]) # [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
8. 切片操作tuple(因为tuple不可变,所以结果仍是tuple)
L = ('A','B','C','D','E') print(L[:3]) # ('A', 'B', 'C')
9. 切片操作字符串
L = ['A','B','C','D','E']
10. 利用切片操作,实现一个trim()函数,去除字符串首尾的空格
s = ' ZHANG JIA ' def trim(s): while s[:1] == " ": s = s[1:] while s[-1:] == " ": s = s[:-1] return s print(trim(s)) #ZHANG JIA
二. 迭代
如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration),在Python中,迭代是通过for … in来完成的。只要是可迭代对象,无论有无下标,都可以迭代。
1. 迭代list
L = [1,2,3] for i in L : print(i) ''' 输出 1 2 3 '''
2. 迭代tuple
T = (1,2,3) for i in T : print(i) ''' 输出 1 2 3 '''
3. 迭代dict的key
d = {'a': 1, 'b': 2, 'c': 3} for i in d : print(i) ''' 输出 a b c '''
4. 迭代dict的value
d = {'a': 1, 'b': 2, 'c': 3} for i in d.values(): print(i) ''' 输出 1 2 3 '''
5. 迭代dict的key和value
d = {'a': 1, 'b': 2, 'c': 3} for i,j in d.items(): print(i,j) ''' 输出 a 1 b 2 c 3 '''
6. 迭代字符串
s = 'JIA' for i in s: print(i) ''' 输出 J I A '''
7. 判断是否是可迭代对象
from collections.abc import Iterable tof = isinstance('abc',Iterable) print(tof) # True
8. enumerate函数可以把一个list变成索引-元素对,即可获取索引
L = ['A','B','C'] for i, j in enumerate(L): print(i,j) ''' 输出 0 A 1 B 2 C '''
三. 列表生成式
列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式。
1. 生成list[n~m]
L = list(range(0,10)) print(L) # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
2. 生成[1×1, 2×2, 3×3, …, 10×10]
L = [x * x for x in range(0,10)] print(L) # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
3. for循环后面还可以加上if判断
L = [x * x for x in range(0,10) if x % 2 == 1] print(L) # [1, 9, 25, 49, 81]
4. 使用两层循环,可以生成全排列:
L = [m + n for m in 'ABC' for n in 'DEF'] print(L) # ['AD', 'AE', 'AF', 'BD', 'BE', 'BF', 'CD', 'CE', 'CF']
5. 列出当前目录下的所有文件和目录名(当前目录下的二级目录获取不到),可以通过一行代码实现:
import os L = [d for d in os.listdir(".")] print(L)
6. 列表生成式也可以使用两个变量来生成list:
d = {'x': 'A', 'y': 'B', 'z': 'C' } print([k + "=" + v for k,v in d.items()]) # ['x=A', 'y=B', 'z=C']
7. 在一个列表生成式中,for前面的if … else是表达式,必须加else,而for后面的if是过滤条件,不能带else,也就是说,for前面的if else用于改变x的值,for后面的if用于筛选哪些x值
print([x if x % 2 == 0 else -x for x in range(1, 11)]) # [-1, 2, -3, 4, -5, 6, -7, 8, -9, 10] print([x for x in range(1, 11)]) #[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
四. 生成器
如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
1. 创建generator方法一:把一个列表生成式的[]改成(),就创建了一个generator
L = [x * x for x in range(0,10)] G = (x * x for x in range(0,10)) print(L) #[0, 1, 4, 9, 16, 25, 36, 49, 64, 81] print(G) #<generator object <genexpr> at 0x0000022CA767DC10>
2. 直接输出G并不能获取对应的值,因为generator保存的是算法,需要通过next()函数获得generator的下一个返回值,如果没有更多的元素时,系统会抛出StopIteration错误
G = (x * x for x in range(0,4)) print(next(G)) # 0 print(next(G)) # 1 print(next(G)) # 4 print(next(G)) # 9 print(next(G)) # 报错:Traceback (most recent call last):
3. next()很少用到,一般使用for循环迭代generator
G = (x * x for x in range(0,4)) for i in G: print(i) ''' 0 1 4 9 '''
4. 创建generator方法二:如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator
# 普通函数 def fib(max): n, a, b = 0, 0, 1 while n < max: print(b) a, b = b, a + b #相当于: t = (b, a + b) a = t[0] b = t[1] ,但不必显式写出临时变量t就可以赋值,t是一个tuple n = n + 1 return 'done' print(fib(6)) # 1 1 2 3 5 8 done # generator def fib(max): n, a, b = 0, 0, 1 while n < max: yield b a, b = b, a + b #相当于: t = (b, a + b) a = t[0] b = t[1] ,但不必显式写出临时变量t就可以赋值,t是一个tuple n = n + 1 return 'done' print(fib(6)) # <generator object fib at 0x000002A2639ADC10>
5. 函数和generator的区别:函数是顺序执行,遇到return语句或者最后一行函数语句就返回,而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
def add(): print("step 1") yield 1 print("step 2") yield 2 print("step 3") yield 3 print(next(add())) # step 1 1 print(next(add())) # step 1 1 o = add() print(next(o)) # step 1 1 print(next(o)) # step 2 2
6. for循环或者next()调用generator时,无法获取generator的return语句的返回值
def fib(max): n, a, b = 0, 0, 1 while n < max: yield b a, b = b, a + b #相当于: t = (b, a + b) a = t[0] b = t[1] ,但不必显式写出临时变量t就可以赋值,t是一个tuple n = n + 1 return 'done' for i in fib(6): print(i) ''' 1 1 2 3 5 8 没有done这个返回值,因为generator中拿不到return的返回值 '''
6. 可以通过捕获StopIteration错误的value来获取return语句的返回值
def fib(max): n, a, b = 0, 0, 1 while n < max: yield b a, b = b, a + b #相当于: t = (b, a + b) a = t[0] b = t[1] ,但不必显式写出临时变量t就可以赋值,t是一个tuple n = n + 1 return 'done' o = fib(5) while True: try: print(next(o)) except StopIteration as e: print(e.value) break ''' 1 1 2 3 5 done '''
五. 迭代器
上面我们说过,可以被for循环的对象啊成为可迭代对象Iterable,而可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
from collections.abc import Iterator L = [1,2,3] print(isinstance(L, Iterator)) #False print(isinstance(iter(L), Iterator)) #True print(iter(L)) #<list_iterator object at 0x000001FAE4B73DF0> print(next(iter(L))) #1
把list、dict、str等Iterable变成Iterator可以使用iter()函数
请登录之后再进行评论