切片

对这种经常取指定索引范围的操作,用循环十分繁琐,因此,Python提供了切片(Slice)操作符,能大大简化这种操作。

作业

  1. #尝试区分这两块代码的区别
  2. def trim(s):
  3. while s[0] == " ":
  4. s=s[1:]
  5. while s[-1] == " ":
  6. s=s[:-1]
  7. return s
  8. #代码2
  9. def trim(s):
  10. while s[:1] == ' ':
  11. s=s[1:]
  12. while s[-1:] == ' ':
  13. s=s[:-1]
  14. return s
  15. #测试
  16. if trim('hello ') != 'hello':
  17. print('测试失败!')
  18. elif trim(' hello') != 'hello':
  19. print('测试失败!')
  20. elif trim(' hello ') != 'hello':
  21. print('测试失败!')
  22. elif trim(' hello world ') != 'hello world':
  23. print('测试失败!')
  24. elif trim('') != '':
  25. print('测试失败!')
  26. elif trim(' ') != '':
  27. print('测试失败!')
  28. else:
  29. print('测试成功!')

迭代

如果给定一个list或者tuple ,我们可以通过 for in来遍历这个list或者tuple,这种遍历我们称之为迭代;

  1. d=[1,2,3,4,5]
  2. for x in d:
  3. print(x)
  1. #一般迭代dice只会输出key
  2. d = {'a': 1, 'b': 2, 'c': 3}
  3. for x in d:
  4. print(x)
  5. #但是也可以输出 value;
  6. for x in d.value():
  7. print(x)
  8. #如果同时迭代两个也可以
  9. for x,k in d.items():
  10. print(f"{x},{k}")
  1. d = "ABCDFEFG"
  2. for x in d:
  3. print(f"{x},")

所以我们不太关系本身能否迭代,但是如果我们需要监测该对象能否迭代这么办呢?使用模块

  1. from collections.abc import Iterable
  2. d = {"a":1,"b":2,"c":3}
  3. print(isinstance(d,Iterable))
  4. isinstance(123, Iterable)

作业

请使用迭代查找一个list中最小和最大值,并返回一个tuple:

  1. def findMinAndMax(L):
  2. if len(L)==0:
  3. return (None, None)
  4. else:
  5. # 初始化最大最小值
  6. min=L[0]
  7. max=L[0]
  8. for x in L:
  9. if max < x:
  10. max = x
  11. if min > x:
  12. min = x
  13. return (min,max)
  14. # 测试
  15. if findMinAndMax([]) != (None, None):
  16. print('测试失败!1')
  17. elif findMinAndMax([7]) != (7, 7):
  18. print('测试失败!2')
  19. elif findMinAndMax([7, 1]) != (1, 7):
  20. print('测试失败!3')
  21. elif findMinAndMax([7, 1, 3, 9, 5]) != (1, 9):
  22. print('测试失败!4')
  23. else:
  24. print('测试成功!')

列表生成式

用更加简略的方式表达, for 循环 ,中间可以加 if 判断

  1. #尝试运行这些代码以理解
  2. L = [x*x for x in range(1,11)]
  3. print(L)
  4. #加判断
  5. L = [x*x for x in range(1,11) if x % 5 == 0]
  6. print(L)
  7. #另一种方式加判断
  8. #筛选出字符串并且转换成小写
  9. L = ['Hello', 'World', 18, 'Apple', None]
  10. L2 =[s.lower() for s in L if isinstance(s,str)]
  11. print(L2)
  12. if L2 == ['hello', 'world', 'apple']:
  13. print('测试通过!')
  14. else:
  15. print('测试失败!')
  16. #else怎么加?else必须加到前面,使得成为一个完整的表达式
  17. #为什么不能加在后面?因为加在后面的 if 是一个筛选条件,不能加else
  18. #为什么 if 加在前面也不行,因为for 前面必须是一个完整的表达式
  19. L = [x if x % 2 == 0 else -x for x in range(1, 11)]
  20. print(L)

生成器

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
可以把generator 单单看作一个算法,他不会输出结果,只是一个计算的公式;

  1. #generator也是一个可迭代对象
  2. L = (x for x in range(1,101) if x%10 ==0) #和列表生成式的区别是使用“()”包裹
  3. a=[]
  4. for x in L:
  5. a.append(x)
  6. print(a)

如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator函数

  1. def fib(max):
  2. n, a, b = 0, 0, 1
  3. while n < max:
  4. print(b)
  5. a, b = b, a + b
  6. n = n + 1
  7. return 'done'
  8. #把 print 输出改为 yield 就变成了一个算法;
  9. def fib(max):
  10. n, a, b = 0, 0, 1
  11. while n < max:
  12. yield b
  13. a, b = b, a + b
  14. n = n + 1
  15. return 'done'

要理解generator的工作原理,它是在for循环的过程中不断计算出下一个元素,并在适当的条件结束for循环。对于函数改成的generator来说,遇到return语句或者执行到函数体最后一行语句,就是结束generator的指令,for循环随之结束。
请注意区分普通函数和generator函数,普通函数调用直接返回结果:

  1. >>> r = abs(6)
  2. >>> r
  3. 6

generator函数的调用实际返回一个generator对象:

  1. >>> g = fib(6)
  2. >>> g
  3. <generator object fib at 0x1022ef948>

迭代器

我们已经知道,可以直接作用于for循环的数据类型有以下几种:
一类是集合数据类型,如list、tuple、dict、set、str等;
一类是generator,包括生成器和带yield的generator function【生成器函数】。
这些可以直接作用于for循环的对象统称为可迭代对象:Iterable
可以使用isinstance()判断一个对象是否是Iterable对象

  1. >>> from collections.abc import Iterable
  2. >>> isinstance([], Iterable)
  3. True
  4. >>> isinstance({}, Iterable)
  5. True
  6. >>> isinstance('abc', Iterable)
  7. True
  8. >>> isinstance((x for x in range(10)), Iterable)
  9. True
  10. >>> isinstance(100, Iterable)
  11. False

但是
可以被next()函数调用并不断返回下一个值的对象称为迭代器Iterator

  1. >>> from collections.abc import Iterator
  2. >>> isinstance((x for x in range(10)), Iterator)
  3. True
  4. >>> isinstance([], Iterator)
  5. False
  6. >>> isinstance({}, Iterator)
  7. False
  8. >>> isinstance('abc', Iterator)
  9. False

小结

凡是可作用于for循环的对象都是Iterable类型;
凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
详细参考
https://www.liaoxuefeng.com/wiki/1016959663602400/1017323698112640