第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 : <generator object squares at 0x11ea93a98> 显示是一个生成器
    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():将句柄位置跳转到指定字节。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,919评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,567评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,316评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,294评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,318评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,245评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,120评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,964评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,376评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,592评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,764评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,460评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,070评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,697评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,846评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,819评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,665评论 2 354