第3章 内建数据结构、函数及文件

  • 元组:固定长度,不可变的Python对象序列。

    tup = 4,5,6 //创建元组最简单的办法
    

    可以通过tuple函数将任意序列或迭代器转换为元组。

    tuple([4,0,2]) // (4,0,2)
    tuple('string') // ('s','t','r','i','n','g')
    

    如果元组中的一个对象是可变的,例如列表,则你可以在它内部进行修改。

    可以使用+连接元组,生成更长的元组。

    将元组乘以整数,可以生成含有多份拷贝的元组。

    • 元组拆包
      如果你想将元组类型的表达式赋给变量,则Python会对等号右边的元组进行拆包。

      tup = 4,5,6
      a,b,c = tup // a = 4,b = 5, c = 6
      tup = 4,5,(6,7)
      a,b,(c,d) = tup // a = 4,b = 5,c = 6, d = 7
      

      一个常用的场景:遍历元组或列表组成的序列。

      seq = [(1,2,3),(4,5,6),(7,8,9)]
      for a,b,c in seq:
          print(a,b,c)  
      # 1 2 3
        4 5 6
        7 8 9
      

      一个更高级的拆包方法:*

      val = 1,2,3,4,5
      a,b,*rest = val // a = 1,b = 2,rest = (3,4,5)
      
    • 元组方法
      由于元组内容和长度无法改变,所以实例方法很少,一个常见的方法count,计算某个数值在元组中出现的次数。

      a = (1,2,3,1,1)
      a.count(1) // 3
      
  • 列表:长度可变,内容可修改。
    list函数,在数据处理中常用于将迭代器或者生成器转化为列表。

    gen = range(10) //生成一个range(0,10)的对象
    list(gen) // [0,1,2,3,4,5,6,7,8,9]
    
    • 增加和移除元素
      append:将元素添加到列表尾部。
      insert:将元素插入到指定位置。
      pop:将特定位置的元素移除并返回。
      remove:定位第一个符合要求的值并移除。
      in:检查一个值是否在列表中。

    • 连接和联合列表

      1. 可以使用+号连接。
      2. 如果有一个已经定义的列表,可以使用extend添加多个元素。
        请注意:通过添加内容来连接列表是一种相对高代价的操作,因为连接过程中创建了新列表,并且还要复制对象,使用extend将元素添加到已经存在的列表中是更好的方式,尤其是在需要构建一个大型列表时。
        everything = []
        for chunk in list_of_lists:
            everything.extend(chunk)
        
        上述实现比下述更快。
        everything = []
        for chunk in list_of_lists: 
            everything = everything + chunk
        
    • 排序
      sort方法:列表内部进行排序(无需新建一个对象)。
      bisect模块:实现了二分搜索和已排序列表的插值。

      import bisect
      c = [1,2,2,2,3,4,7]
      bisect.bisect(c,2) // 返回 4,表示2应该插入列表c中第4个位置。
      bisect.insort(c,6) // c = [1,2,2,2,3,4,6,7]
      
    • 切片
      将序列赋值给变量:

      seq = [1,2,3,4]
      seq[4:5] = [5,6] // seq [1,2,3,4,5,6]
      

      步进值可以在第二个冒号后面使用,当需要对列表或元组进行翻转时,可以向步进传值-1。

    • 内建序列函数

      • enumerate:遍历一个序列会同时返回当前元素的索引。
        用法:for i,value in enumerate(collection):

      • sorted:函数返回一个根据任意序列中的元素新建的已排序列表。

        sorted([7,1,2,6,0,3,2]) // [0,1,2,2,3,6,7]
        sorted('horse race') // [' ','a','c','e','e','h','o','r','r','s']
        
      • zip:将列表、元组或其他序列的元素配对,新建一个元组构成的列表。

        seq1 = ['foo','bar','baz']
        seq2 = ['one','two','three']
        zipped = zip(seq1,seq2)
        list(zipped) # [('foo','one'),('bar','two'),('baz','three')]
        

        zip可以处理任意长度的序列,生成列表的长度由最短的序列决定。

        seq3 = [False,True]
        list(zipped(seq1,seq2,seq3)) # [('foo','one',False),('bar','two','True)]
        

        常用的场景:同时遍历多个序列,有时候会和enumerate同时使用:

        for i,(a,b) in enumerate(zip(seq1,seq2)):
            print('{0}:{1},{2}'.format(i,a,b)) 
            # 0:foo,one
            # 1:bar,two
            # 2:baz,three
        

        给定一个已经配对的序列时,zip函数可以将其拆分。

        pitchers = [('Nolan','Ryan'),('Roger','Clemens'),('Schilling','Curt')]
        firstname,lastname = zip(*pitchers) 
        #firstname:('Nolan', 'Roger', 'Schilling')
        #lastname:('Ryan', 'Clemens', 'Curt')
        
    • reversed:将序列元素倒序排列。

  • 字典:也称为哈希表,键值对方式存在。

    d1 = {} #创建字典  
    d[1] = 'some value' # 向d中添加键值对
    1 in d #检查d中是否存在键 1
    

    del:按键删除值。
    pop:按键删除值并返回。
    keys():返回字典中的键。
    value():返回字典中的值。
    update:将两个字典合并。

    d1 = {1:2}
    d2 = {3:4}
    d1.update(d2) # d1 = {1:2,3:4}
    
    • 默认值
      通常情况下,会有这样的代码逻辑,如果键key存在于字典中,那么令value等于它的值,否则令value等于其他值。

      if key in dict:
        value = dict[key]
      else:
        value = default_value
      

      上述代码可以简写为:value = dict.get(key,default_value),如果不写参数default_value,key不存在时会返回None。

    • setdefault
      可以用来设定字典默认值。
      dict.setdefault(key,value)

      • 一个例子:根据首字母分类为包含列表的字典。
        words = ['apple','bat','bar','atom','book']
        by_letter = {}
        for word in words:
            letter = word[0]
            if letter not in by_letter:
              by_letter[letter] = [word]
            else:
              by_letter[letter].append(word)
        
        setdefault方法就是为了这个目的而产生的,可以将上述代码写为:
        for word in words:
          letter = word[0]
          by_letter.setdefault(letter,[]).append(word)
        
  • 集合
    可以理解为只含有键的字典。

    issubset:检查一个集合是否是另一个集合的子集。
    例:{1,2,3}.issubset{1,2,3,4,5}

    当两个集合内的内容一模一样时,两个集合才相等。
    {1,2,3} == {3,2,1}

  • 列表、集合和字典的推导式
    列表推导式是最受欢迎的Python语言特性之一!
    基本形式:[expr for val in collection if condition],其中if condition过滤条件可以忽略/
    与下面for循环等价:

    result = []
    for val in collection:
      if condition:
      result.append(expr)
    

    字典和集合推导式是列表推导式的拓展:
    dict = {key-expr:value:expr for value in collection if condition}
    set = {expr for value in collection if condition}
    假设我们想要一个集合,集合里包含列表中字符串的长度,我们可以通过集合推导式实现:
    unique_length = {len(x) for x in strings}
    也可以使用map函数更函数化,更简洁的表达:
    set(map(len,string))

  • 嵌套列表推导式
    假设有一个包含列表的列表:

    all_data = [['John','Emily','Michael','Mary','Steven'],['Maria','Juan','Javier','Natalia','Pilar']]
    

    我们想要一个列表包含所有含有2个以上字母'e'的名字,for循环写法如下:

    names_of_interest = []
    for names in all_data:
        enough_es = [name for name in names if name.count('e') >= 2]
        names_of_interest.extend(enough_es)
    

    实际上更简洁的写法如下,用嵌套列表推导式:
    result = [ name for names in all_data for name in names if name.count('e') >= 2]

  • lambda函数
    例:lambda x,y:x+y,返回的是一个函数对象,返回x+y的值。
    因为没有__name__属性,所以叫做匿名函数。

  • 柯里化
    现在我们有一个函数如下:

    def add_nums(x,y):
        return x+y
    

    使用这个函数衍生出一个新的函数:
    add_five = lambda y:add_nums(5,y)
    上述过程就叫做柯里化。

  • 生成器
    创建一个生成器,只需要将函数返回关键字return改为yield

    def squares(n=10):
        print('Generating squares from 1 to {0}'.format(n ** 2))
        for i in range(1,n+1):
            yield i ** 2
    

    当你实际调用生成器时,它并不会立即执行。
    直到你请求生成器的元素时,它才会执行代码。

    gen = squares() // gen :  显示是一个生成器
    for x in gen:
        print(x)
    // Generating square from 1 to 100
    1
    4
    9
    16
    25
    36
    49
    64
    81
    100
    

    由上述可见,for循环后面可以跟一个生成器generator或者迭代器iterator,用来每次向循环中返回一个对象。

    • 生成器表达式
      gen = ( x ** 2 for x in range(100))
      上述表达式与下面代码是等价的:
      def _make_gen():
          for x in range(100):
              yield x ** 2
      
      很多情况下生成器表达式作为函数参数用于替代列表表达式:
      sum(x ** 2 for x in range(100)) #328350
      dict((i,i ** 2) for i in range(5)) # {0:0,1:1,2:4,3:9,4:16,5:25}
      
  • 文件与操作系统
    打开文件进行读取或写入,使用内建函数open和绝对、相对路径。
    f = open(path)
    默认情况下文件是以只读模式r打开的。之后我们可以像处理列表一样处理文件中的内容。
    当你使用open来创建文件对象时,结束操作后一定要显式的关闭文件。
    f.close()

    另一种更简单的方式:with open(path) as f:,文件会在with代码块后自动关闭。

    • 一些操作句柄的方法:
      f.read() :读取()个字符。
      f.tell():给出当前句柄的位置。
      f.seek():将句柄位置跳转到指定字节。

你可能感兴趣的:(第3章 内建数据结构、函数及文件)