廖雪峰--python教程:笔记三

高级特性:
前面我们简单的聊了一下Python的数据类型、语句和函数,接下来来聊聊Python的高级特性

切片:
取一个list、tuple、str一部分内容是很常见的操作,而切片操作,可以让这一个过程变得非常简单。
对于一个列表集合:
L = ['student','teacher','doctor','engineer']
索引是从0开始,到n-1;所以, L[0] : 'student'; L[3] : 'engineer'

L[0:2]:表示,取['student','teacher'],即索引为0,1的值,不包括索引2对应的值

a = L[:]:表示,将变量a指向一个新的赋值的L,并不是L指向的列表对象

L[:2]和L[0:2]是相同的,如果第一个索引为0,则可以省略

L[1:]:表示为['teacher','doctor','engineer'],即包括第一个索引1对应的值,同样的,如果最后一个索引省略,则表示最后一个索引为n(列表的元素个数)

Python还可以对列表元素倒着取:
L[-3:-1]:表示,取['teacher','doctor']

还有比较好玩的是,切片还可以跳跃着取元素:
L = list(range(100)),则,L 为 [0,1,...,99]
如:前十个数中,每两个取一个: L[:10:2],或者对于整个数列L每五个取一个L[::5]

tuple和str字符串也可以像list集合那样去操作,只不过返回的是tuple和str类型而已。

练习:
利用切片操作,去除字符串的首尾空格,注意不要调用str的strip()方法:

def trim(s):
  ''' 首先,判断输入字符串,是否为空字符串,若为空,则返回这个字符串;
    若不为空,则进行下一步判断:
    判断该字符串是否首尾为空格,如为空格,则递归地调用该函数本身
  '''
  if len(s)==0:
      return s
  elif s[0] == ' ':
      return trim(s[1:])
  elif s[-1] == ' ':
      return trim(s[:-1])
  return s
 
扫描二维码关注公众号,回复: 3484527 查看本文章

迭代:

对于一个给定的list,tuple,str,dict类型,我们可以通过for...in来循环地取出其元素,这种遍历,称其为迭代(Iteration)。因此,我们称list,tuple,str,dict类型为可迭代对象(Iterable)。那么,我们怎么判断一个对象是否是可迭代对象呢?
方法是,通过collections模块中的Iterable类型判断:
isinstance('abc',Iterable) 返回:True
isinstance是一个内置函数,可以判断一个对象是否是指定的类型

还可以两个变量同时迭代,
如:
for x,y in [(1,2),(3,4),(5,6)]:
  print(x,y)

如迭代字典d={'a':1,'b':2,'c':3}
for k,v in d.items():
  print(k,'='.v)
Python 字典(Dictionary) items() 函数以列表返回可遍历的(键, 值) 元组数组。
用法: dict.items()

还可以通过Python的内置函数enumerate()枚举函数,将列表变成索引-元素对:
L = ['a','b','c']
for i,value in enumerate(L):
  print(i,value)
enumerate() 函数用于将一个可遍历的数据对象(元组或如列表、字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中
enumerate(sequence, [start=0]):sequence-- 一个序列、迭代器或其他支持迭代对象。start--起始位置

练习:
请使用迭代查找一个list中的最大值和最小值:

def findMinAndMax(L):
    if L == []:
        return (None,None)
    max = min = L[0]
    for i in L:
        if i > max:
        max = i
    elif i < min:
        min = i
    return (min,max)

列表生成器:

这是一个非常好玩且有用的构造列表的好方法,可以取代好多循环,所以,简单,明了。
如:list(range(100)),[0,...99]

加入for循环在列表中:
[x*x for x in range(5)],[0,1,4,9,16]

加入for循环和if语句判断在列表中:
[x for x in range(5) if x % 2==0],[0,2,4]

两个变量和加入两个for循环在列表中:
[m+n for m in 'ABC' for n in 'XY'],['AX', 'AY', 'BX', 'BY', 'CX', 'CY']

练习:

如果list既包含字符串类型,又包含整数和None,将字符串类型的变为小写,其他忽略
L = ['Hello','World',18,'Apple',None]
L2 = [x.lower() for x in L if isinstace(x,str)],['hello', 'world', 'apple']

生成器:

如果我们使用一个很大的列表的前几个元素时,我们通过列表生成器来创建这个列表在内存中,是非常浪费内存空间的,再假设,如果这个的列表的元素可以通过某种推算的方法推算出来,那么,我们是否可以仅仅存这个推算的方法,在取列表元素的时候,通过迭代的操作,一次取一个,而不需要存这个列表的所有元素呢?--Python提供了这个方便,叫做生成器(generator)

生成器,有两种方法可以构成:
第一种,将列表生成器中的[]换成(),就OK了。
如:g = (x*x for x in range(5)),则L就是一个生成器啦,我们通过next(g)的方式可以从第一个元素取到最后一个元素,当取到最后的元素时,若还调用next(g),则会抛出StopIteration停止迭代的异常,我们并不会这么傻地使用这种方式取生成器g中的元素,而是通过for循环的方式取(生成器是一个迭代对象),并且这个方式取到g中最后一个元素后,就停止啦,不会有StopIteration异常。

第二种,复杂的生成器,并不是第一种能够实现了的,所以,我们通过函数来实现。
如,斐波拉契数列1,1,2,3,5,8,13...

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

如果一个函数中包含了'yield'关键字,那么这个就不是一个普通的函数,而是一个generator。调用next()函数取fib元素时,在执行时,遇到yield就会中断,下次又继续运行。但是,我们都是用for循环来取生成器fib元素的,用for循环调用generator时,拿不到return语句返回的值。如果想要拿到返回值,就必须捕获StopIteration错误,返回值包含在StopIteration的valule中。
如:

g = fib(6)
while True:
    try:
        x = next(g)
        print('g',x)
    except StopIteration as e:
        print('Generator return value:',e.value)
        break    

练习:
杨辉三角:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
...
把每一行当成一个列表,然后写一个generator,不断地输出下一行的list

def triangles(n):
    '''
    [1] + [2] + [1] 为: [1,2,1]
    首先,第一个列表L是[1],也就是第一行,然后第接下来的行,由列表生成式构造:
    第二行:
    [1] + [L[i] + L[i+1] for i in range(len(L) -1)] + [1]
    当,range(0)时,想象成循环的话,这是不执行的,也就是[L[i] +     L[i+1] for i in range(len(L)-1)] 是空列表[]。
    第三行:[1] + [L[i] + L[i+1] for i in range(len(L) -1)] + [1]
  '''
    L, index = [1], 0
    while index < n:
        yield L
        L = [1] + [L[i] + L[i+1] for i in range(len(L)-1)] + [1]
        index += 1
    return 'done'

for x in triangles(6):
    print(x)

输出:
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]

迭代器:

我们知道,用于for循环的类型可以分为两类:
一是集合类型的: list,tuple,str,dict等
另一类是生成器:列表生成式的生成器和带yield关键字的生成器函数

这些直接作用于for循环的对象,我们称其为可迭代对象(Iterable),然而生成器不但可以for循环遍历,还可以通过next()函数取其元素。可以被next()函数调用不断返回下一个值的对象称为迭代器:Iterator。

可以把str,list,tuple,dict等Iterable,通过iter()函数变为Iterator
如:
from collections import Iterator
isinstance(iter('abc'),Iterator) -- 返回 True

Python的Iterator对象表示的是一个数据流,Iterator对象可以通过next()函数调用不断的返回下一个数据,直到没有数据时,抛出StopIteration错误。可以把数据流看作一个有序序列,但我们却不能提前得知序列的长度,只能不断通过next()函数实现按需计算下一个数据,因此Iterator的计算是惰性的。
Iterator可以表示一个自然数集合,而list则不能。

实际上,Python中的for循环就是一个不断通过next()函数实现的:
for x in [1,2,3,4,5]:
  pass

实际上,是这样实现
it = iter([1,2,3,4,5])
while True:
  try:
    x = next(it)
  except StopIteration:
    break

猜你喜欢

转载自www.cnblogs.com/double-lin/p/9757953.html