廖雪峰老师的Python教程 第三弹之切片,迭代,列表生成式,生成器,迭代器 fighting 😆
切片 (取指定索引范围 )
格式:arr[开始索引:结束索引:Step]
开始索引 默认0,可不写; 结束索引默认为数组的长度, 获取的范围为 开始索引-结束索引 之间, 不包括结束索引; Step默认为1。
L = ['0', '1', '2', '3', '4']
print( L[0:3]) # ['0', '1', '2'] 获取从索引0开始,到索引3之间的,不包括索引3的数
print( L[-2:-1]) # ['3'] 从倒数第二个开始到倒数第一个之间
print( L[::2]) # 步长step为2时结果 ['0', '2', '4']
前10个数: L[:10]
后10个数: L[-10:]
10-20之间: L[10:20]
tuple也是一种list,唯一区别是tuple不可变。因此,tuple也可以用切片操作,只是操作的结果仍是tuple:
print( (0, 1, 2, 3, 4, 5)[:3]) # (0, 1, 2)
字符串’xxx’也可以看成是一种list,每个元素就是一个字符。因此,字符串也可以用切片操作,只是操作结果仍是字符串:print( 'HelloWorld!'[:3]) # Hel
利用切片操作,实现一个trim()函数,去除字符串首尾的空格,注意不要调用str的strip()方法:
def myTrim(s):
while(s[:1] == ' '):
s = s[1:]
while(s[-1:] == ' '):
s = s[:-1]
return s
print(myTrim(' aa '))
迭代 (Iterable)
Python中,迭代是通过for … in来完成的
使用for循环时,只要作用于一个可迭代对象,for循环就可以正常运行
dict ,list ,tuple,string 都可以遍历
- demo-dict :
默认情况下,dict迭代的是key。
如果要迭代value,可以用for value in d.values()
,
如果要同时迭代key和value,可以用for k, v in d.items()
。
#dict 字典的存储不是按照list的方式顺序排列,所以迭代出的结果顺序很可能不一样。
d = {'a': 1, 'aa': 2, 'c': 3}
for key in d:
print(key)
for value in d.values():
print(value)
for key,value in d.items():
print(key,value)
- demo-string:
在es6中这个也可以直接遍历,可以参考博主的这篇文章《es6入门提升总结一之字符串的遍历器接口》 es6写法:for (let codePoint of 'foo') {}
for ch in 'HelloWorld':
print(ch)
- demo-list:
如何判断一个对象是可迭代对象呢?方法是通过collections模块的Iterable类型判断:
from collections import Iterable
print(isinstance({'a':1,'b':2},Iterable)) # dict True
print(isinstance('hello world',Iterable)) # str True
print(isinstance([1,2,3,4,5],Iterable)) # list True
print(isinstance((1,2,3,4,5,6),Iterable)) # tuple True
print(isinstance(111,Iterable)) # num False
如果要对list实现类似Java那样的下标循环怎么办?Python内置的 enumerate (枚举)函数可以把一个list变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身:
for i, value in enumerate(['A', 'B', 'C']):
print(i, value)
# 结果:
0 A
1 B
2 C
- demo-tuple:
for (x) in ([1,2],[3,4],[5,6]):
print(x)
# 结果:
[1, 2]
[3, 4]
[5, 6]
# 获取tuple中list的值
for (x,y) in ([1,2],[3,4],[5,6]):
print(x,y)
# 结果:
1 2
3 4
5 6
列表生成式 (List Comprehensions)
列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式。举个例子,要生成list
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
可以用list(range(1, 11))
:
- 生成
[1x1, 2x2, 3x3, ..., 10x10]
格式
print([x*x for x in range(1,11)])
# [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
- for循环后面还可以加上if判断,这样我们就可以筛选出仅偶数的平方:
在一个列表生成式中,for前面的if … else是表达式,而for后面的if是过滤条件,不能带else
print([x*x for x in range(1,11) if x%2==0])
# [4, 16, 36, 64, 100]
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([m+n for m in 'abc' for n in 'xyz'])
# ['ax', 'ay', 'az', 'bx', 'by', 'bz', 'cx', 'cy', 'cz']
- 列出当前目录下的所有文件和目录名,可以通过一行代码实现
import os
print([d for d in os.listdir('.')])
# ['hello-world', 'notebook.ipynb', 'python入门笔记2和3.ipynb']
生成器 (generator)
这个看着也有点眼熟, 哈哈 原来在es6中也有这个generator
在Python中,这种一边循环一边计算的机制,称为生成器:generator。
有了生成器,我们可以在需要的时候才去创建这个元素出来,可以节省内存的使用
定义 generator 的一种方法:将一个列表生成式的 [] 改成 ()
g = (x **2 for x in range(10))
print(next(g)) # 0
print(next(g)) # 1
print(next(g)) # 4
print(next(g)) # 9
# 直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。
正确的方法是使用for循环,因为generator也是可迭代对象:
g = (x **2 for x in range(10))
for n in g:
print(n)
定义generator的另一种方法,如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator:
最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
# 斐波拉契数列
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'
for a in fib(6):
print(a) # 1 1 2 3 5 8
注意:a, b = b, a + b 等于 t = (b, a + b) # t是一个tuple a = t[0] b = t[1]
for循环,拿不到这个return 的 ‘done’,如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中:
def fib(max):
n, a, b = 0, 0, 1
while n < max:
yield b
a, b = b, a + b
n = n + 1
return 'done'
f=fib(6)
while True:
try:
x=next(f)
print('g', x)
except StopIteration as e:
print('Generator return value: ', e.value)
break
# g 1
# g 1
# g 2
# g 3
# g 5
# g 8
# Generator return value: done
迭代器 (Iterator)
看到这个迭代器,就想到在java中,只能通过这个iterator在遍历中删除这个元素,而不能在普通的for循环中去删除这个集合的元素 😄
可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator
from collections import Iterator
print(isinstance((x for x in range(10)),Iterator)) # True
print(isinstance([],Iterator)) # False
print(isinstance((),Iterator)) # False
print(isinstance('a',Iterator)) # False
直接作用于for循环的数据类型有以下几种:
一类是集合数据类型,如list、tuple、dict、set、str等;
一类是generator,包括生成器和带yield的generator function。
这些可以直接作用于for循环的对象统称为可迭代对象:Iterable
上面迭代中的3.demo-list有说到如何判断一个对象是可迭代对象
Iterable 可以通过 iter() 函数转变成 Iterator
from collections import Iterator
a=[1,2,3,4,5]
b=iter(a)
print(isinstance(b, Iterator))
print(next(b)) # 1
Iterator对象表示的是一个数据流
Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。