1、切片css
一、切片支持list,tuple和string;python
二、切片的基本格式 object[start:end:step],切片结果不包含object[end];算法
三、倒数切片ruby
>>> L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']
>>> L[-2:] ['Bob', 'Jack'] >>> L[-2:-1] ['Bob']
2、迭代
一、判断一个对象是可迭代对象呢?方法是经过collections模块的Iterable类型判断:app
>>> from collections import Iterable >>> isinstance('abc', Iterable) # str是否可迭代 True >>> isinstance([1,2,3], Iterable) # list是否可迭代 True >>> isinstance(123, Iterable) # 整数是否可迭代 False
二、默认状况下,dict迭代的是key。若是要迭代value,能够用for value in d.values()
,若是要同时迭代key和value,能够用for k, v in d.items()
。函数
因为字符串也是可迭代对象,所以,也能够做用于for
循环;ui
三、Python内置的enumerate
函数能够把一个list变成索引-元素对,这样就能够在for
循环中同时迭代索引和元素自己:spa
>>> for i, value in enumerate(['A', 'B', 'C']): ... print(i, value) ... 0 A 1 B 2 C
上面的for
循环里,同时引用了两个变量,在Python里是很常见的,好比下面的代码:code
>>> for x, y in [(1, 1), (2, 4), (3, 9)]: ... print(x, y) ... 1 1 2 4 3 9
3、列表生成式(List Comprehensions)对象
若是要生成[1x1, 2x2, 3x3, ..., 10x10]
怎么作?方法一是循环:
>>> L = [] >>> for x in range(1, 11): ... L.append(x * x) ... >>> L [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
可是循环太繁琐,而列表生成式则能够用一行语句代替循环生成上面的list:
>>> [x * x for x in range(1, 11)] [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
写列表生成式时,把要生成的元素x * x
放到前面,后面跟for
循环,就能够把list建立出来,十分有用,多写几回,很快就能够熟悉这种语法。
for循环后面还能够加上if判断,这样咱们就能够筛选出仅偶数的平方:
>>> [x * x for x in range(1, 11) if x % 2 == 0] [4, 16, 36, 64, 100]
还可使用两层循环,能够生成全排列:
>>> [m + n for m in 'ABC' for n in 'XYZ'] ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
三层和三层以上的循环就不多用到了。
4、生成器
经过列表生成式,咱们能够直接建立一个列表。可是,受到内存限制,列表容量确定是有限的。并且,建立一个包含100万个元素的列表,不只占用很大的存储空间,若是咱们仅仅须要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
因此,若是列表元素能够按照某种算法推算出来,那咱们是否能够在循环的过程当中不断推算出后续的元素呢?这样就没必要建立完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
要建立一个generator,有不少种方法。第一种方法很简单,只要把一个列表生成式的[]
改为()
,就建立了一个generator:
>>> L = [x * x for x in range(10)] >>> L [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> g = (x * x for x in range(10)) >>> g <generator object <genexpr> at 0x1022ef630>
建立L
和g
的区别仅在于最外层的[]
和()
,L
是一个list,而g
是一个generator。
咱们能够经过next()
函数得到generator的下一个返回值:
>>> next(g) 0 >>> next(g) 1 >>> next(g) 4 >>> next(g) 9 >>> next(g) 16 >>> next(g) 25 >>> next(g) 36 >>> next(g) 49 >>> next(g) 64 >>> next(g) 81 >>> next(g) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
generator保存的是算法,每次调用next(g)
,就计算出g
的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration
的错误。
固然,上面这种不断调用next(g)
实在是太变态了,正确的方法是使用for
循环,由于generator也是可迭代对象:
>>> g = (x * x for x in range(10)) >>> for n in g: ... print(n)
建立了一个generator后,基本上永远不会调用next()
,而是经过for
循环来迭代它,而且不须要关心StopIteration
的错误。
next()forStopIteration
定义generator的另外一种方法,若是一个函数定义中包含关键字,那么这个函数就再也不是一个普通函数,而是一个generator:
yield
generator和函数的执行流程不同。函数是顺序执行,遇到return
语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()
的时候执行,遇到yield
语句返回,再次执行时从上次返回的yield
语句处继续执行。
举个简单的例子,定义一个generator,依次返回数字1,3,5:
def odd(): print('step 1') yield 1 print('step 2') yield(3) print('step 3') yield(5)
调用该generator时,首先要生成一个generator对象,而后用next()
函数不断得到下一个返回值:
>>> o = odd()
>>> next(o) step 1 1 >>> next(o) step 2 3 >>> next(o) step 3 5 >>> next(o) Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
能够看到,odd
不是普通函数,而是generator,在执行过程当中,遇到yield
就中断,下次又继续执行。执行3次yield
后,已经没有yield
能够执行了,因此,第4次调用next(o)
就报错。
回到fib
的例子,咱们在循环过程当中不断调用yield
,就会不断中断。固然要给循环设置一个条件来退出循环,否则就会产生一个无限数列出来。
一样的,把函数改为generator后,咱们基本上历来不会用next()
来获取下一个返回值,而是直接使用for
循环来迭代:
>>> for n in fib(6): ... print(n) ... 1 1 2 3 5 8
可是用for
循环调用generator时,发现拿不到generator的return
语句的返回值。若是想要拿到返回值,必须捕获StopIteration
错误,返回值包含在StopIteration
的value
中:
>>> g = fib(6) >>> while True: ... try: ... x = next(g) ... 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
凡是可做用于for
循环的对象都是Iterable
类型;
凡是可做用于next()
函数的对象都是Iterator
类型,它们表示一个惰性计算的序列;
集合数据类型如list
、dict
、str
等是Iterable
但不是Iterator
,不过能够经过iter()
函数得到一个Iterator
对象。
Python的for
循环本质上就是经过不断调用next()
函数实现的