再一次重新学习Python——高级特性

  • 切片

L[0:3]表示,从索引0开始取,直到索引3为止,但不包括索引3。即索引0,1,2,正好是3个元素。如果第一个索引是0,还可以省略。

同样支持倒数切片

>>> L = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']
>>> L[-2:]
['Bob', 'Jack']
>>> L[-2:-1]
['Bob']

记住倒数第一个元素的索引是-1

前10个数,每两个取一个:

>>> L[:10:2]
[0, 2, 4, 6, 8]

甚至什么都不写,只写[:]就可以原样复制一个list。

tuple也是一种list,唯一区别是tuple不可变。因此,tuple也可以用切片操作,只是操作的结果仍是tuple:

>>> (0, 1, 2, 3, 4, 5)[:3]
(0, 1, 2)

字符串'xxx'或Unicode字符串u'xxx'也可以看成是一种list,每个元素就是一个字符。因此,字符串也可以用切片操作,只是操作结果仍是字符串:

>>> 'ABCDEFG'[:3]
'ABC'
>>> 'ABCDEFG'[::2]
'ACEG'
  • 迭代

dict和字符串这种没有下标的数据类型也可以进行迭代 

>>> d = {'a': 1, 'b': 2, 'c': 3}
>>> for key in d:
...     print key
...
a
c
b

因为dict的存储不是按照list的方式顺序排列,所以,迭代出的结果顺序很可能不一样。

默认情况下,dict迭代的是key。如果要迭代value,可以用for value in d.itervalues(),如果要同时迭代key和value,可以用for k, v in d.iteritems()

由于字符串也是可迭代对象,因此,也可以作用于for循环:

>>> for ch in 'ABC':
...     print ch
...
A
B
C

 通过collections模块的Iterable类型判断某对象是否为可迭代的对象。

Python内置的enumerate函数可以把一个list变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身:

>>> for i, value in enumerate(['A', 'B', 'C']):
...     print i, value
...
0 A
1 B
2 C

上面的for循环里,同时引用了两个变量,在Python里是很常见的,比如下面的代码:

>>> for x, y in [(1, 1), (2, 4), (3, 9)]:
...     print x, y
...
1 1
2 4
3 9

 enumerate() 方法的语法:

enumerate(sequence, [start=0])

参数

  • sequence -- 一个序列、迭代器或其他支持迭代对象。
  • start -- 下标起始位置。

返回值

返回 enumerate(枚举) 对象。

  •  列表生成式

>>> [x * x for x in range(1, 11)]
[1, 4, 9, 16, 25, 36, 49, 64, 81, 100]

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']

两个变量 

>>> d = {'x': 'A', 'y': 'B', 'z': 'C' }
>>> [k + '=' + v for k, v in d.iteritems()]
['y=B', 'x=A', 'z=C']

把一个list中所有的字符串变成小写:

>>> L = ['Hello', 'World', 'IBM', 'Apple']
>>> [s.lower() for s in L]
['hello', 'world', 'ibm', 'apple']
  • 生成器

如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器(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 0x104feab40>

创建Lg的区别仅在于最外层的[]()L是一个list,而g是一个generator。

怎么打印出generator的每一个元素呢?

如果要一个一个打印出来,可以通过generator的next()方法:

>>> g.next()
0
>>> g.next()
1

正确的方法是使用for循环,因为generator也是可迭代对象

g = (x * x for x in range(10))
>>> for n in g:
        print n

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

def fib(max):
    n, a, b = 0, 0, 1
    while n < max:
        yield b
        a, b = b, a + b
        n = n + 1

最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。 

要理解generator的工作原理,它是在for循环的过程中不断计算出下一个元素,并在适当的条件结束for循环。对于函数改成的generator来说,遇到return语句或者执行到函数体最后一行语句,就是结束generator的指令,for循环随之结束。

猜你喜欢

转载自blog.csdn.net/Saikikky/article/details/81083323