学习笔记:Python3 高级特性

仅为个人查阅使用,如有错误还请指正。

使用高级特性的原因就是为了代码能够简洁。代码越少,开发效率越高。

  • 切片

    列表和元组的切片操作完全相同。字符串也相差不多。

    以列表为例

    L = ["Harden", "Durant", "Jordan", "Curry", "O'Neal"]
    
    
    print(L[0:3])             # 取前3个元素
    # output:['Harden', 'Durant', 'Jordan']
    print(L[:3])              # 第一个索引是0,还可以省略
    # output:['Harden', 'Durant', 'Jordan']
    print(L[1:3])             # 从索引1开始,取出2个元素出来
    # output:['Durant', 'Jordan']
    print(L[:])                   # L[:]实际上是复制,这种复制是浅拷贝。
    # output:['Harden', 'Durant', 'Jordan', 'Curry', "O'Neal"]
    print(L[::2])             # 第三个参数表示每N个取一个
    # output:['Harden', 'Jordan', "O'Neal"]
    
    # 倒序切片:记住倒数第一个元素的索引是-1。倒序切片包含起始索引,不包含结束索引。
    
    print(L[-2:])             # 取最后两个元素
    # output:['Curry', "O'Neal"]
    print(L[:-2])             # 删去最后两个元素
    # output:['Harden', 'Durant', 'Jordan']
    print(L[-3:-1])               # 从索引-3开始,取出两个元素
    # output:['Jordan', 'Curry']
    print(L[-4:-1:2])         # 从索引-4开始,每两个取一个,到索引-1前结束
    # output:['Durant', 'Curry']
  • 迭代

    通过for循环来遍历字符串,列表,元组,字典等。遍历就相当于是迭代

    如果学过C语言或者Java语言都知道,迭代是通过下标来完成的。请看下面这个代码。

    for (i=0; i<list.length; i++) {
        n = list[i];
    }

    而Python是通过for...in...来完成的。请看下面这个代码。

    for i in range(1, 100):
        if i % 7 == 0:
            print(i)

    很明显,Python的迭代是取出元素本身,而非元素的索引。

    如果想要在迭代的时候获取索引,可以通过enumerate()函数来获取。

    L = ["Harden", "Durant", "Jordan", "Curry", "O'Neal"]
    
    for index, name in enumerate(L):
      print(index, "--", name)
    
    # output:
    0 -- Harden
    1 -- Durant
    2 -- Jordan
    3 -- Curry
    4 -- O'Neal

    enumerate()函数本质是把L变成了

    [(0, "Harden"), (1, "Durant"), (2, "Jordan"), (3, "Curry"), (4, "O'Neal")]

    相当于是每个元素变成了元组。那也可以通过下标去访问。

    注意:这个写法只是用来理解概念,推荐使用上面一种方法,因为方便简洁。

    for i in enumerate(L):
      index = i[0]
      name = i[1]
      print(index, "--", name)

    前面说了列表,元组,现在来说说一个比较特别的字典

    注意:Python 3.6版本之前,字典是无序的,本环境是Python 3.6.5是有序的。

    • 默认情况,字典遍历是内容是key

      d = {"PF":"Jordan", "SF":"Durant", "C":"O'Neal", "SG":"Harden", "PG":"Curry"}
      
      for key in d:
          print(key)
      
      # output:
      PF
      SF
      C
      SG
      PG    
    • 如果需要遍历value,就使用d.values()

      for value in d.values():

    • 如果key,value都需要遍历,就使用d.items()

      for k, v in d.items()

    如果判断一个对象是可迭代对象呢?需要通过collections模块的Iterable类型判断。

    其实我觉得没有必要,把常用的记住就好了。稍微了解一下有这么一种方法就行。

    from collections import Iterable
    
    print(isinstance("a", Iterable))      # 字符串是
    print(isinstance([a, b, c], Iterable))    # 列表是
    print(isinstance(123, Iterable))      # 整数不是
  • 列表生成式

    就是用一行代码实现一个列表,而且这个列表是可以灵活多变的。

    • 生成列表

      比如我们之前要生成一个列表,最傻瓜的办法就是自己创建一个。

      稍微好一点的就用list(range(1, 11)),然后生成1到10这10个数字。

      或者稍微多变一点,list(range(1, 10, 2)),然后生成1到10的奇数。

      如果要添加一些运算,可能需要for循环来辅助。但是循环太繁琐。

      这时我们可以使用Python特有的列表生成式来解决这个问题,而且是一行代码。

      • 比如要生成[1×1,2×2, 3×3,...,10×10]

        [x * x for x in range(1, 11)]

      • 比如要生成[1×2,3×4, 5×6, 7×8,...,99×100]

        [x * (x + 1) for x in range(1, 100, 2)]

    • 条件过滤

      顾名思义就是,可以在列表生成式里面加if语句。

      比如,把列表中的所有字符串变成小写,非字符串元素进行过滤

      L = [35, "Durant", "Jordan", "Curry", "O'Neal"]
      
      print([name.lower() for name in L if isinstance(name, str)])
    • 多层表达式

      利用多层循环,找出对称的3位数,例如,101,121,232,222。

      [x*100+y*10+z for x in range(1,10) for y in range(10) for z in range(10) if x == z]

  • 生成器

    前面提到了列表生成式,也明白列表容量会受到限制。占用太多的存储空间。

    如果一个列表的元素可以通过某种算法推算出来,就可以节省很大空间,而这种机制就是生成器。

    创建一个生成器,最简单的方法,就是用()来表示。例如

    g = (x * x for x in range(10))
    
    print(g)
    
    # output:<generator object <genexpr> at 0x00000239CCD59C50>
    # 可以看到这是一个生成器,怎么去获取呢?使用next()函数,一个一个打印出来。
    print(next(g)) # output:0
    print(next(g)) # output:1
    
    # 需要注意的是:生成器保存的是算法。
    # 上面的next()方法是有点傻的,如果没有元素了,还会调用异常。所以一般都是用for循环去遍历的。
    
    for n in g:
        print(n, end=",")
    
    # output:0,1,4,9,16,25,36,49,64,81,

    前面说了,生成器是保存算法的,如果算法复杂,列表生成式的for循环无法实现,可以用函数来实现

    以斐波那契数列来说,它的规则是除了第一个和第二个数外,任意一个数都由前两个数相加所得。

    1,1,2,3,5,8,13,21,34,55,...

    很显然,用列表生成式写不出来,但是,用函数可以很方便的实现。

    def fib(max):
        n, a, b = 0, 0, 1
        while n < max:
            print(b)
            a, b = b, a + b
            n = n + 1
        return 'over'
    
    print(fib(6))
    
    # output:
    1
    1
    2
    3
    5
    8
    over

    如上所述,这个fib函数实现了这个算法规则,整体的逻辑也符合生成器。但他始终是个函数。

    需要通过一个关键字yield,把函数变成生成器。这是另一种创建生成器的方法。

    执行流程:第一次迭代,会执行到yield b,然后返回b的值,作为第一个迭代的返回值,那么第2次迭代,不会再去执行函数,而是从yield b的下一条语句继续执行,直到再次遇到 yield。依此类推。

    def fib(max):
        n, a, b = 0, 0, 1
        while n < max:
            yield b
            a, b = b, a + b
            n = n + 1
        return 'over'
    
    print(fib(6))
    # <generator object fib at 0x000001494CE09A40>
    for n in fib(6):
        print(n)

    总结:生成器可以用[]或者yield,可迭代对象又多了一个(生成器)

  • 迭代器

    前面在讲生成器的时候,有一个next()函数。迭代器的定义就是通过它来的。

    能够被next()函数调用,并不断返回下一个值的对象称为迭代器。

    前面讲迭代的时候,讲到,如果要判断一个对象是否等着该对象,有一个isinstance()函数。

    迭代器的数据类型名称是:Iterator,迭代器相当于是一个数据流。

    from collections import Iterator
    
    
    print(isinstance((x for x in range(10)), Iterator))       # 生成器是
    print(isinstance([1,2,3], Iterator))                  # 列表不是
    print(isinstance({"a":1, "b":2}, Iterator))               # 字典不是
    print(isinstance('abc', Iterator))                        # 字符串不是

    有些同学可能会问,列表,字典,字符串都是可迭代对象,为什么不是迭代器。

    这是因为迭代器表示的是一个数据流。因为它可以被next()函数调用并不断返回下一个数据。

    但是可以把可迭代对象变成迭代器,通过iter()函数。

    L = [1,2,3,4,5]
    
    a = iter(L)
    
    print(next(a))
    # output:1
    print(next(a))
    # output:2
    print(next(a))
    # output:3

    总结:迭代器的两个基本方法 iter()next()

猜你喜欢

转载自www.cnblogs.com/lowkeyao/p/11297262.html