我们来介绍Python中非常有用的高级特性,一行代码能实现的功能,决不写5行代码
    切片
    切片(Slice)操作符
    L[0:3]表示,从索引0开始取,直到索引3为止,但不包括索引3。即索引0,1,2,正好是3个元素。
    只写[:]就可以原样复制一个list
    如果第一个索引是0,还可以省略:

    L[:3]

    倒数切片
    L[-2:] 倒数第2个至倒数第1个
    记住倒数第一个元素的索引是-1
    a[::-1] 将列表倒过来
    字符串’xxx’或Unicode字符串u’xxx’也可以看成是一种list,每个元素就是一个字符。因此,字符串也可以用切片操作,只是操作结果仍是字符串
    在很多编程语言中,针对字符串提供了很多各种截取函数,其实目的就是对字符串切片。Python没有针对字符串的截取函数,只需要切片一个操作就可以完成,非常简单。
    前段时间Jeff Atwood 推广了一个简单的编程练习叫FizzBuzz,问题引用如下: 写一个程序,打印数字1到100,3的倍数打印“Fizz”来替换这个数,5的倍数打印“Buzz”,对于既是3的倍数又是5的倍数的数字打印“FizzBuzz”。 这里有一个简短的方法解决这个问题:
    for x in range(101):print”fizz”[x%3_4::]+”buzz”[x%5_4::]or x
    print后面分为两部分,第一部分是”fizz”[x%3_4::]+”buzz”[x%5_4::],第二部分是x。两部分使用逻辑或连接。如果第一部分为空,则最终结果为第二部分的结果。如果第一部分非空,则最终结果为第一部分。
    第一部分由两个字符串连接而成,第一个字符串为”fizz”[x%3_4::],如果x是3的倍数,则x%3=0,那么”fizz”[x%3_4::]=”fizz”[0::]=”fizz”;如果x不是3的倍数,则x%3=1或2,那么”fizz”[x%34::]=”fizz”[4::]或”fizz”[8::]=””。
    第二个字符串为”buzz”[x%5_4::],如果x是5的倍数,那么”buzz”[x%5_4::]=”buzz”[0::]=”buzz”;如果x不是5的倍数,那么x%5=1,2,3,4,那么”buzz”[x%5
    4::]=”buzz”[4::]或”buzz”[8::]或”buzz”[12::]或”buzz”[16::]或”buzz”[20::]=””
    由此,如果x是3的倍数,第一部分为”fizz”;如果x是5的倍数,第一部分为”buzz”;如果x既是3的倍数,又是5的倍数,则第一部分为”buzzfizz”,如果既不是3的倍数,也不是5的倍数,则第一部分为””。
    迭代
    如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration)
    Python的for循环抽象程度要高于Java的for循环,因为Python的for循环不仅可以用在list或tuple上,还可以作用在其他可迭代对象上
    关键是要有一个可迭代对象
    如何判断一个对象是可迭代对象呢?方法是通过collections模块的Iterable类型判断

    1. from collections import Iterable
    2. isinstance('abc', Iterable)

    Python内置的enumerate函数可以把一个list变成索引-元素对,这样就可以在for循环中同时迭代索引和元素本身
    任何可迭代对象都可以作用于for循环,包括我们自定义的数据类型,只要符合迭代条件,就可以使用for循环。
    列表 生成式

    d = {‘x’: ‘A’, ‘y’: ‘B’, ‘z’: ‘C’ } [k + ‘=’ + v for k, v in d.items()] [‘y=B’, ‘x=A’, ‘z=C’] L = [‘Hello’, ‘World’, ‘IBM’, ‘Apple’] [s.lower() for s in L] [‘hello’, ‘world’, ‘ibm’, ‘apple’]

    使用内建的isinstance函数可以判断一个变量是不是字符串
    upper2 = [‘HelloBang’, 19, ‘World’, ‘IBM’, ‘Apple’]
    lower2 = [s.lower() for s in upper2 if isinstance(s,str)] //会自动将不是str的值过滤掉
    lower2 = [s.lower() if isinstance(s,str) else s for s in upper2 ] //不是str的值还会不变,不会被过滤

    • 在一个列表生成式中,for前面的if … else是表达式,而for后面的if是过滤条件,不能带else

    生成器
    在Python中,这种一边循环一边计算的机制,称为生成器(Generator)。
    创建一个generator的两种方法

    • 只要把一个列表生成式的[]改成()
    • g = (x * x for x in range(10))
    • for n in g:
      … print(n)

    • yield关键字
    • 如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator
    • 案例: 斐波拉契数列

    这里,最难理解的就是generator和函数的执行流程不一样。

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

    要理解generator的工作原理,它是在for循环的过程中不断计算出下一个元素,并在适当的条件结束for循环。对于函数改成的generator来说,遇到return语句或者执行到函数体最后一行语句,就是结束generator的指令,for循环随之结束。
    迭代器
    凡是可作用于for循环的对象都是Iterable类型;
    凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列(如上面讲到的生成器);
    集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。
    Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。