01. Python3 数据类型(一)

系统 1084 0

01. Python3 数据类型(一)

python3 基本数据类型大致分为 可变数据类型 不可变数据类型 ,不可变有 Number(数字)、String(字符串)、Tuple(元组) ,可变有 List(列表)Dictionary(字典)Set(集合)

文章目录

  • 01. Python3 数据类型(一)
    • Number
      • 关于Number一些运算和内置函数
    • 字符串
      • 索引 (通用序列操作)
      • 切片[左索引:右索引:步长] (通用序列操作)
      • 常用方法
      • 格式化方法format()
    • List(列表)
      • 序列 UML
        • 检验值是否存在序列中 (通用序列操作)
      • 序列的*
      • 序列的+ 和 +=
      • 常用方法
    • 列表推导式和生成器表达式
      • 易读性
      • 生成器表达式
      • 列表推导同filter和map的比较
    • 切片
      • 对对象进行切片
      • 切片原理
      • 给切片赋值
    • 元组
      • 元组拆包
      • 具名元组
    • 字典
      • Map UML
      • 字典推导
      • dict、 defaultdict 和 OrderedDict
      • 用setdefault处理找不到的键 (用于更新操作)
      • 映射的弹性键查询
      • 字典的变种
      • 不可变映射类型
    • 集合
      • 集合 UML
      • set 和 frozenset
      • 集合字面量
      • 集合推导
      • 集合的操作
    • dict和set的背后
      • dict的实现及其导致的结果
      • set的实现以及导致的结果

Number

python3 支持int、float、bool、complex(复数)

关于Number一些运算和内置函数

            
              
                # /运算结果为小数
              
              
                print
              
              
                (
              
              
                4
              
              
                /
              
              
                2
              
              
                )
              
              
                # ==>2.0
              
              
                print
              
              
                (
              
              
                5
              
              
                /
              
              
                4
              
              
                )
              
              
                # ==>1.25
              
              
                # //运算结果舍弃余数
              
              
                print
              
              
                (
              
              
                9.0
              
              
                //
              
              
                4
              
              
                )
              
              
                # ==>2.0
              
              
                print
              
              
                (
              
              
                9.2
              
              
                //
              
              
                4
              
              
                )
              
              
                # ==>2.0
              
              
                print
              
              
                (
              
              
                9
              
              
                //
              
              
                4
              
              
                )
              
              
                # ==>2
              
              
                # %运算保留余数
              
              
                print
              
              
                (
              
              
                9.0
              
              
                %
              
              
                4
              
              
                )
              
              
                # ==>1.0
              
              
                print
              
              
                (
              
              
                9.2
              
              
                %
              
              
                4
              
              
                )
              
              
                # ==>1.1999999999999993
              
              
                print
              
              
                (
              
              
                9
              
              
                %
              
              
                4
              
              
                )
              
              
                # ==>1
              
              
                # **运算为幂运算
              
              
                print
              
              
                (
              
              
                2
              
              
                **
              
              
                -
              
              
                1
              
              
                )
              
              
                # ==>0.5
              
              
                # 绝对值abs(Number)
              
              
                print
              
              
                (
              
              
                abs
              
              
                (
              
              
                -
              
              
                3
              
              
                )
              
              
                )
              
              
                # ==>3
              
              
                # 向原点0取整
              
              
                print
              
              
                (
              
              
                int
              
              
                (
              
              
                -
              
              
                2.3
              
              
                )
              
              
                )
              
              
                # ==>-2
              
              
                # 四舍五入round(no_complex, 0)
              
              
                print
              
              
                (
              
              
                round
              
              
                (
              
              
                3.1415
              
              
                ,
              
              
                3
              
              
                )
              
              
                )
              
              
                # ==>3.142
              
            
          

字符串

字符串是以单引号’或双引号"括起来的任意文本,比如’abc’,"xyz"等等。

索引 (通用序列操作)

            
              
                # 正索引
              
              
                print
              
              
                (
              
              
                "abcde"
              
              
                [
              
              
                0
              
              
                ]
              
              
                )
              
              
                # ==>a
              
              
                # 负索引,-n:倒数第n个元素
              
              
                print
              
              
                (
              
              
                "abcde"
              
              
                [
              
              
                -
              
              
                1
              
              
                ]
              
              
                )
              
              
                # ==>e
              
            
          

切片[左索引:右索引:步长] (通用序列操作)

            
              
                # 切片str[m:n],m默认为0,n默认为len(str)
              
              
                print
              
              
                (
              
              
                "abcde"
              
              
                [
              
              
                1
              
              
                :
              
              
                3
              
              
                ]
              
              
                )
              
              
                # ==>bc
              
              
                print
              
              
                (
              
              
                "abcde"
              
              
                [
              
              
                1
              
              
                :
              
              
                ]
              
              
                )
              
              
                # ==>bcde
              
              
                print
              
              
                (
              
              
                "abcde"
              
              
                [
              
              
                :
              
              
                2
              
              
                ]
              
              
                )
              
              
                # ==>ab
              
              
                print
              
              
                (
              
              
                'abcde'
              
              
                [
              
              
                0
              
              
                :
              
              
                5
              
              
                :
              
              
                2
              
              
                ]
              
              
                )
              
              
                # ==>ace
              
            
          

常用方法

            
              
                # 大小写转换
              
              
                print
              
              
                (
              
              
                "Python"
              
              
                .
              
              upper
              
                (
              
              
                )
              
              
                )
              
              
                # ==>PYTHON
              
              
                print
              
              
                (
              
              
                "Python"
              
              
                .
              
              lower
              
                (
              
              
                )
              
              
                )
              
              
                # ==>python
              
              
                print
              
              
                (
              
              
                "hello world"
              
              
                .
              
              capitalize
              
                (
              
              
                )
              
              
                )
              
              
                # ==>Hello world
              
              
                print
              
              
                (
              
              
                "hello world"
              
              
                .
              
              title
              
                (
              
              
                )
              
              
                )
              
              
                # ==>Hello World
              
              
                # 非重叠字符串的数量
              
              
                print
              
              
                (
              
              
                "ablllabllab"
              
              
                .
              
              count
              
                (
              
              
                "ll"
              
              
                )
              
              
                )
              
              
                # ==>2
              
              
                # 字符串查找
              
              
                print
              
              
                (
              
              
                "hihihi"
              
              
                .
              
              find
              
                (
              
              
                "hi"
              
              
                )
              
              
                )
              
              
                # ==>0
              
              
                print
              
              
                (
              
              
                "hihihi"
              
              
                .
              
              rfind
              
                (
              
              
                "hi"
              
              
                )
              
              
                )
              
              
                # ==>4
              
              
                # 字符串替换所有
              
              
                print
              
              
                (
              
              
                "To a To b"
              
              
                .
              
              replace
              
                (
              
              
                'To'
              
              
                ,
              
              
                'to'
              
              
                )
              
              
                )
              
              
                # ==>to a to b
              
              
                # 首尾去除,默认空格
              
              
                print
              
              
                (
              
              
                "first-first-end"
              
              
                .
              
              strip
              
                (
              
              
                'find'
              
              
                )
              
              
                )
              
              
                # ==>rst-first-e
              
              
                print
              
              
                (
              
              
                "first-first-end"
              
              
                .
              
              strip
              
                (
              
              
                'first-'
              
              
                )
              
              
                )
              
              
                # ==>end
              
              
                print
              
              
                (
              
              
                "first-end-end"
              
              
                .
              
              rstrip
              
                (
              
              
                '-end'
              
              
                )
              
              
                )
              
              
                # ==>first
              
              
                # 用于输出的对齐,默认填充空格
              
              
                print
              
              
                (
              
              
                "hello"
              
              
                .
              
              ljust
              
                (
              
              
                9
              
              
                ,
              
              
                '-'
              
              
                )
              
              
                +
              
              
                "hello"
              
              
                .
              
              center
              
                (
              
              
                9
              
              
                ,
              
              
                '+'
              
              
                )
              
              
                +
              
              
                "hello"
              
              
                .
              
              rjust
              
                (
              
              
                9
              
              
                ,
              
              
                '-'
              
              
                )
              
              
                )
              
              
                # ==>hello----++hello++----hello
              
            
          

格式化方法format()

List(列表)

列表是一种序列,因此索引和切片与字符串类似

序列 UML

01. Python3 数据类型(一)_第1张图片

检验值是否存在序列中 (通用序列操作)

            
              
                print
              
              
                (
              
              
                2
              
              
                in
              
              
                [
              
              
                1
              
              
                ,
              
              
                2
              
              
                ,
              
              
                3
              
              
                ,
              
              
                4
              
              
                ]
              
              
                )
              
              
                # ==>True
              
              
                print
              
              
                (
              
              
                'bc'
              
              
                in
              
              
                'abcde'
              
              
                )
              
              
                # ==>True
              
            
          

序列的*

            
              
                # 一个包含 3 个列表的列表, 嵌套的 3 个列表各自有 3 个元素来代表井字游戏的一行方块
              
              
board 
              
                =
              
              
                [
              
              
                [
              
              
                '_'
              
              
                ]
              
              
                *
              
              
                3
              
              
                for
              
               i 
              
                in
              
              
                range
              
              
                (
              
              
                3
              
              
                )
              
              
                ]
              
              
                # [['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]
              
              
board
              
                [
              
              
                1
              
              
                ]
              
              
                [
              
              
                2
              
              
                ]
              
              
                =
              
              
                'X'
              
              
                # [['_', '_', '_'], ['_', '_', 'X'], ['_', '_', '_']]
              
              
                # *的一个特性,复制的是引用
              
              
weird_board 
              
                =
              
              
                [
              
              
                [
              
              
                '_'
              
              
                ]
              
              
                *
              
              
                3
              
              
                ]
              
              
                *
              
              
                3
              
              
                # [['_', '_', '_'], ['_', '_', '_'], ['_', '_', '_']]
              
              
weird_board
              
                [
              
              
                1
              
              
                ]
              
              
                [
              
              
                2
              
              
                ]
              
              
                =
              
              
                'O'
              
              
                # [['_', '_', 'O'], ['_', '_', 'O'], ['_', '_', 'O']]
              
            
          

序列的+ 和 +=

            
              l1 
              
                =
              
              
                [
              
              
                1
              
              
                ,
              
              
                2
              
              
                ,
              
              
                3
              
              
                ,
              
              
                4
              
              
                ,
              
              
                5
              
              
                ]
              
              
l2 
              
                =
              
               l1

              
                # +操作是先将[1, 2, 3, 4, 5]和[6, 7, 8]相加,将结果的引用赋值给l2
              
              
l2 
              
                =
              
               l2 
              
                +
              
              
                [
              
              
                6
              
              
                ,
              
              
                7
              
              
                ,
              
              
                8
              
              
                ]
              
              
                print
              
              
                (
              
              l1
              
                )
              
              
                # ==>[1, 2, 3, 4, 5]
              
              
                print
              
              
                (
              
              l2
              
                )
              
              
                # ==>[1, 2, 3, 4, 5, 6, 7, 8]
              
              
                print
              
              
                (
              
              
                id
              
              
                (
              
              l1
              
                )
              
              
                ==
              
              
                id
              
              
                (
              
              l2
              
                )
              
              
                )
              
              
                # ==>False
              
              

l1 
              
                =
              
              
                [
              
              
                1
              
              
                ,
              
              
                2
              
              
                ,
              
              
                3
              
              
                ,
              
              
                4
              
              
                ,
              
              
                5
              
              
                ]
              
              
l2 
              
                =
              
               l1

              
                # +=操作是就地在l2后面加[6, 7, 8]
              
              
l2 
              
                +=
              
              
                [
              
              
                6
              
              
                ,
              
              
                7
              
              
                ,
              
              
                8
              
              
                ]
              
              
                print
              
              
                (
              
              l1
              
                )
              
              
                # ==>[1, 2, 3, 4, 5, 6, 7, 8]
              
              
                print
              
              
                (
              
              l2
              
                )
              
              
                # ==>[1, 2, 3, 4, 5, 6, 7, 8]
              
              
                print
              
              
                (
              
              
                id
              
              
                (
              
              l1
              
                )
              
              
                ==
              
              
                id
              
              
                (
              
              l2
              
                )
              
              
                )
              
              
                # ==>True
              
            
          

常用方法

            
              l1 
              
                =
              
              
                [
              
              
                '1'
              
              
                ,
              
              
                '2'
              
              
                ,
              
              
                '3'
              
              
                ,
              
              
                '4'
              
              
                ,
              
              
                '1'
              
              
                ]
              
              
l1
              
                .
              
              count
              
                (
              
              
                '1'
              
              
                )
              
              
                # 统计某个元素出现的次数
              
              
l1
              
                .
              
              index
              
                (
              
              
                '1'
              
              
                )
              
              
                # 找出某个元素的第一次出现的位置
              
              
l1
              
                .
              
              reverse
              
                (
              
              
                )
              
              
                # 将元素进行反转
              
              
l1
              
                .
              
              sort
              
                (
              
              reverse
              
                =
              
              
                True
              
              
                )
              
              
                # 对列表进行反向排序,列表被改变,返回值是空
              
              
l1
              
                .
              
              append
              
                (
              
              
                '5'
              
              
                )
              
              
                # 向末尾添加一个元素
              
              
l1
              
                .
              
              insert
              
                (
              
              
                3
              
              
                ,
              
              
                '6'
              
              
                )
              
              
                # 向指定索引位置添加一个元素
              
              
l1
              
                .
              
              extend
              
                (
              
              
                [
              
              
                '1'
              
              
                ,
              
              
                '2'
              
              
                ]
              
              
                )
              
              
                # 向末尾添加,等同于 li + ['1','2']
              
              
l1
              
                .
              
              pop
              
                (
              
              
                3
              
              
                )
              
              
                # 删除指定索引位置的一个元素,默认末尾
              
              
l1
              
                .
              
              remove
              
                (
              
              
                '1'
              
              
                )
              
              
                # 移除列表中的第一个匹配元素
              
              
l1
              
                .
              
              clear
              
                (
              
              
                )
              
              
                # 清空所有元素
              
              
                # split和join
              
              
                print
              
              
                (
              
              
                "1,2,3,4,5"
              
              
                .
              
              split
              
                (
              
              
                ','
              
              
                )
              
              
                )
              
              
                # ==>['1', '2', '3', '4', '5']
              
              
                # join参数中的元素不能为数字
              
              
                print
              
              
                (
              
              
                ","
              
              
                .
              
              join
              
                (
              
              
                [
              
              
                '1'
              
              
                ,
              
              
                '2'
              
              
                ,
              
              
                '3'
              
              
                ,
              
              
                '4'
              
              
                ,
              
              
                '5'
              
              
                ]
              
              
                )
              
              
                )
              
              
                # ==>1,2,3,4,5
              
            
          

列表推导式和生成器表达式

列表推导是构建列表(list) 的快捷方式, 而生成器表达式则可以用来创建其他任何类型的序列。 如果你的代码里并不经常使用它们, 那么很可能你错过了许多写出可读性更好且更高效的代码的机会。

易读性

            
              
                # 把一个字符串变成 Unicode 码位的列表
              
              
symbols 
              
                =
              
              
                '$¢£¥€¤'
              
              
code 
              
                =
              
              
                [
              
              
                ]
              
              
                for
              
               symbol 
              
                in
              
               symblos
              
                :
              
              
    codes
              
                .
              
              append
              
                (
              
              
                ord
              
              
                (
              
              symbol
              
                )
              
              
                )
              
              
                # 等价于
              
              
symbols 
              
                =
              
              
                '$¢£¥€¤'
              
              
code 
              
                =
              
              
                [
              
              
                ord
              
              
                (
              
              symbol
              
                )
              
              
                for
              
               symbol 
              
                in
              
               symbols
              
                ]
              
            
          

生成器表达式

虽然也可以用列表推导来初始化元组、 数组或其他序列类型, 但是生成器表达式是更好的选择。 这是因为生成器表达式背后遵守了迭代器协议, 可以逐个地产出元素, 而不是先建立一个完整的列表, 然后再把这个列表传递到某个构造函数里。 前面那种方式显然能够节省内存。

生成器表达式的语法跟列表推导差不多, 只不过把方括号换成圆括号而已。

            
              symbols 
              
                =
              
              
                '$¢£¥€¤'
              
              
                tuple
              
              
                (
              
              
                ord
              
              
                (
              
              symbol
              
                )
              
              
                for
              
               symbol 
              
                in
              
               symbols
              
                )
              
              
                [
              
              
                ord
              
              
                (
              
              symbol
              
                )
              
              
                for
              
               symbol 
              
                in
              
               symbols 
              
                if
              
              
                ord
              
              
                (
              
              symbol
              
                )
              
              
                >
              
              
                0
              
              
                ]
              
            
          

列表推导同filter和map的比较

filter 和 map 合起来能做的事情, 列表推导也可以做, 而且还不需要借助难以理解和阅读的 lambda 表达式。

            
              
                # 选出所有大于127的Unicode 码位
              
              
symbols 
              
                =
              
              
                '$¢£¥€¤'
              
              
beyond_ascii 
              
                =
              
              
                list
              
              
                (
              
              
                filter
              
              
                (
              
              
                lambda
              
               c
              
                :
              
               c 
              
                >
              
              
                127
              
              
                ,
              
              
                map
              
              
                (
              
              
                ord
              
              
                ,
              
               symbols
              
                )
              
              
                )
              
              
                )
              
              
                # beyond_ascii==>[162, 163, 165, 8364, 164]
              
              
                # 等价于
              
              
beyond_ascii 
              
                =
              
              
                [
              
              
                ord
              
              
                (
              
              s
              
                )
              
              
                for
              
               s 
              
                in
              
               symbols 
              
                if
              
              
                ord
              
              
                (
              
              s
              
                )
              
              
                >
              
              
                127
              
              
                ]
              
            
          

切片

像列表(list)、元组(tuple) 和字符串(str) 这类序列类型都支持切片操作, 但是实际上切片操作比人们所想象的要强大很多。

对对象进行切片

s[a:b:c] 的形式对 s 在 a 和 b之间以 c 为间隔取值。 c 的值还可以为负, 负值意味着反向取值。

            
              s 
              
                =
              
              
                'bicycle'
              
              
                print
              
              
                (
              
              s
              
                [
              
              
                :
              
              
                :
              
              
                3
              
              
                ]
              
              
                )
              
              
                # ==>bye
              
              
                print
              
              
                (
              
              s
              
                [
              
              
                :
              
              
                :
              
              
                -
              
              
                1
              
              
                ]
              
              
                )
              
              
                # ==>elcycib
              
              
                print
              
              
                (
              
              s
              
                [
              
              
                :
              
              
                :
              
              
                -
              
              
                2
              
              
                ]
              
              
                )
              
              
                # ==>eccb
              
            
          

切片原理

a:b:c 这种用法只能作为索引或者下标用在 [] 中来返回一个切片对象: slice(a, b, c)。

seq[start:stop:step] 进行求值的时候, Python 会调用 seq.__getitem__(slice(start, stop, step))

            
              
                class
              
              
                MySeq
              
              
                :
              
              
                def
              
              
                __getitem__
              
              
                (
              
              self
              
                ,
              
               index
              
                )
              
              
                :
              
              
                return
              
               index
s 
              
                =
              
               MySeq
              
                (
              
              
                )
              
              
                print
              
              
                (
              
              s
              
                [
              
              
                1
              
              
                ]
              
              
                )
              
              
                # ==>1
              
              
                print
              
              
                (
              
              s
              
                [
              
              
                1
              
              
                :
              
              
                4
              
              
                ]
              
              
                )
              
              
                # ==>slice(1, 4, None)
              
              
                print
              
              
                (
              
              s
              
                [
              
              
                1
              
              
                :
              
              
                4
              
              
                :
              
              
                2
              
              
                ,
              
              
                7
              
              
                :
              
              
                9
              
              
                ]
              
              
                )
              
              
                # ==>(slice(1, 4, 2), slice(7, 9, None))
              
            
          

通过审查 slice 它有 start、 stop 和 step 数据属性, 以及indices 方法。

            
              
                # S.indices(len) -> (start, stop, stride) 
              
              
                # 给定长度为 len 的序列, 计算 S 表示的扩展切片的起始(start)和结尾(stop) 索引, 以及步幅(stride) 。 超出边界的索引会被截掉, 这与常规切片的处理方式一样。 
              
              
                # 假设有个长度为 5 的序列, 例如 'ABCDE'
              
              
                # 'ABCDE'[:10:2] 等同于 'ABCDE'[0:5:2]
              
              
                slice
              
              
                (
              
              
                None
              
              
                ,
              
              
                10
              
              
                ,
              
              
                2
              
              
                )
              
              
                .
              
              indices
              
                (
              
              
                5
              
              
                )
              
              
                # ==>(0, 5, 2)
              
              
                # 'ABCDE'[-3:] 等同于 'ABCDE'[2:5:1]
              
              
                slice
              
              
                (
              
              
                -
              
              
                3
              
              
                ,
              
              
                None
              
              
                ,
              
              
                None
              
              
                )
              
              
                .
              
              indices
              
                (
              
              
                5
              
              
                )
              
              
                # ==>(2, 5, 1)
              
            
          

给切片赋值

如果把切片放在赋值语句的左边, 或把它作为 del 操作的对象, 我们就可以对序列进行嫁接、 切除或就地修改操作。

ps : 赋值语句右边必须是一个可迭代对象

            
              l 
              
                =
              
              
                list
              
              
                (
              
              
                range
              
              
                (
              
              
                10
              
              
                )
              
              
                )
              
              
                # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
              
              
l
              
                [
              
              
                2
              
              
                :
              
              
                5
              
              
                ]
              
              
                =
              
              
                [
              
              
                20
              
              
                ,
              
              
                30
              
              
                ]
              
              
                # [0, 1, 20, 30, 5, 6, 7, 8, 9]
              
              
                del
              
               l
              
                [
              
              
                5
              
              
                :
              
              
                7
              
              
                ]
              
              
                # [0, 1, 20, 30, 5, 8, 9]
              
              
l
              
                [
              
              
                3
              
              
                :
              
              
                :
              
              
                2
              
              
                ]
              
              
                =
              
              
                [
              
              
                11
              
              
                ,
              
              
                22
              
              
                ]
              
              
                # [0, 1, 20, 11, 5, 22, 9]
              
            
          

元组

元组除了用作不可变的列表, 它还可以用于没有字段名的记录。

            
              
                # 经纬度
              
              
lax_coordinates 
              
                =
              
              
                (
              
              
                33.9425
              
              
                ,
              
              
                -
              
              
                118.408056
              
              
                )
              
              
                # 东京市的一些信息:市名、年份、人口(单位: 百万)、人口变化(单位: 百分比)和面积(单位: 平方千米)。
              
              
city
              
                ,
              
               year
              
                ,
              
               pop
              
                ,
              
               chg
              
                ,
              
               area 
              
                =
              
              
                (
              
              
                'Tokyo'
              
              
                ,
              
              
                2003
              
              
                ,
              
              
                32450
              
              
                ,
              
              
                0.66
              
              
                ,
              
              
                8014
              
              
                )
              
            
          

元组拆包

            
              
                # 简单的拆包
              
              
lax_coordinates 
              
                =
              
              
                (
              
              
                33.9425
              
              
                ,
              
              
                -
              
              
                118.408056
              
              
                )
              
              
latitude
              
                ,
              
               longitude 
              
                =
              
               lax_coordinates 
              
                # 元组拆包
              
              
                # 交换变量的值
              
              
a
              
                ,
              
               b 
              
                =
              
              
                1
              
              
                ,
              
              
                2
              
              
a
              
                ,
              
               b 
              
                =
              
               b
              
                ,
              
               a


              
                # 用 * 运算符把一个可迭代对象拆开作为函数的参数
              
              
                # 20除8 等于 2余4
              
              
                print
              
              
                (
              
              
                divmod
              
              
                (
              
              
                20
              
              
                ,
              
              
                8
              
              
                )
              
              
                )
              
              
                #==>(2, 4)
              
              
t 
              
                =
              
              
                (
              
              
                20
              
              
                ,
              
              
                8
              
              
                )
              
              
                print
              
              
                (
              
              
                divmod
              
              
                (
              
              
                *
              
              t
              
                )
              
              
                )
              
              
                #==>(2, 4)
              
              
                # 使用_占位符
              
              
_
              
                ,
              
               b 
              
                =
              
              
                (
              
              
                1
              
              
                ,
              
              
                2
              
              
                )
              
              
                print
              
              
                (
              
              b
              
                )
              
              
                #==>2
              
              
                # Python3 在平行赋值中使用*args
              
              
a
              
                ,
              
               b
              
                ,
              
              
                *
              
              rest 
              
                =
              
              
                range
              
              
                (
              
              
                5
              
              
                )
              
              
                # (0, 1, [2, 3, 4])
              
              
a
              
                ,
              
               b
              
                ,
              
              
                *
              
              rest 
              
                =
              
              
                range
              
              
                (
              
              
                3
              
              
                )
              
              
                # (0, 1, [2])
              
              
a
              
                ,
              
               b
              
                ,
              
              
                *
              
              rest 
              
                =
              
              
                range
              
              
                (
              
              
                2
              
              
                )
              
              
                # (0, 1, [])
              
              
a
              
                ,
              
              
                *
              
              body
              
                ,
              
               c
              
                ,
              
               d 
              
                =
              
              
                range
              
              
                (
              
              
                5
              
              
                )
              
              
                # (0, [1, 2], 3, 4)
              
              
                *
              
              head
              
                ,
              
               b
              
                ,
              
               c
              
                ,
              
               d 
              
                =
              
              
                range
              
              
                (
              
              
                5
              
              
                )
              
              
                # ([0, 1], 2, 3, 4)
              
              
                # 嵌套元组拆包
              
              
                (
              
              a
              
                ,
              
               b
              
                ,
              
              
                (
              
              c
              
                ,
              
               d
              
                )
              
              
                )
              
              
                =
              
              
                (
              
              
                1
              
              
                ,
              
              
                2
              
              
                ,
              
              
                (
              
              
                3
              
              
                ,
              
              
                4
              
              
                )
              
              
                )
              
            
          

具名元组

collections.namedtuple 是一个工厂函数, 它可以用来构建一个带字段名的元组和一个有名字的类——这个带名字的类对调试程序有很大帮助

            
              
                from
              
               collections 
              
                import
              
               namedtuple
City 
              
                =
              
               namedtuple
              
                (
              
              
                'City'
              
              
                ,
              
              
                'name country population coordinates'
              
              
                )
              
              
tokyo 
              
                =
              
               City
              
                (
              
              
                'Tokyo'
              
              
                ,
              
              
                'JP'
              
              
                ,
              
              
                36.933
              
              
                ,
              
              
                (
              
              
                35.689722
              
              
                ,
              
              
                139.691667
              
              
                )
              
              
                )
              
              
                print
              
              
                (
              
              tokyo
              
                )
              
              
                # ==>City(name='Tokyo', country='JP', population=36.933, coordinates=(35.689722,139.691667))
              
              
                print
              
              
                (
              
              tokyo
              
                .
              
              population
              
                )
              
              
                # ==>36.933
              
              
                print
              
              
                (
              
              tokyo
              
                .
              
              coordinates
              
                )
              
              
                # ==>(35.689722, 139.691667)
              
            
          

字典

字典这个数据结构活跃在所有 Python 程序的背后, 即便你的源码里并没有直接用到它。

Map UML

01. Python3 数据类型(一)_第2张图片

字典推导

字典推导(dictcomp) 可以从任何以键值对作为元素的可迭代对象中构建出字典。

            
              DIAL_CODES 
              
                =
              
              
                [
              
              
                (
              
              
                86
              
              
                ,
              
              
                'China'
              
              
                )
              
              
                ,
              
              
                (
              
              
                91
              
              
                ,
              
              
                'India'
              
              
                )
              
              
                ,
              
              
                (
              
              
                1
              
              
                ,
              
              
                'United States'
              
              
                )
              
              
                ,
              
              
                (
              
              
                62
              
              
                ,
              
              
                'Indonesia'
              
              
                )
              
              
                ,
              
              
                (
              
              
                55
              
              
                ,
              
              
                'Brazil'
              
              
                )
              
              
                ,
              
              
                (
              
              
                92
              
              
                ,
              
              
                'Pakistan'
              
              
                )
              
              
                ,
              
              
                (
              
              
                880
              
              
                ,
              
              
                'Bangladesh'
              
              
                )
              
              
                ,
              
              
                (
              
              
                234
              
              
                ,
              
              
                'Nigeria'
              
              
                )
              
              
                ,
              
              
                (
              
              
                7
              
              
                ,
              
              
                'Russia'
              
              
                )
              
              
                ,
              
              
                (
              
              
                81
              
              
                ,
              
              
                'Japan'
              
              
                )
              
              
                ,
              
              
                ]
              
              
country_code 
              
                =
              
              
                {
              
              country
              
                :
              
               code 
              
                for
              
               code
              
                ,
              
               country 
              
                in
              
               DIAL_CODES
              
                }
              
              
                # {'China': 86, 'India': 91, 'Bangladesh': 880, 'United States': 1,'Pakistan': 92,'Japan': 81, 'Russia': 7, 'Brazil': 55, 'Nigeria':234, 'Indonesia': 62}
              
              
x 
              
                =
              
              
                {
              
              code
              
                :
              
               country
              
                .
              
              upper
              
                (
              
              
                )
              
              
                for
              
               country
              
                ,
              
               code 
              
                in
              
               country_code
              
                .
              
              items
              
                (
              
              
                )
              
              
                if
              
               code 
              
                <
              
              
                66
              
              
                }
              
              
                # {1: 'UNITED STATES', 55: 'BRAZIL', 62: 'INDONESIA', 7: 'RUSSIA'}
              
            
          

dict、 defaultdict 和 OrderedDict

后面两个数据类型是 dict 的变种, 位于 collections 模块内。

不同方法

dict defaultdict OrderedDict 说明
d.__copy__() 用于支持 copy.copy
d.default_factory __missing__ 函数中被调用的函数, 用以给未找到的元素设置值
d.__missing__(k) __getitem__ 找不到对应键的时候, 这个方法会被调用
d.move_to_end(k,[last]) 把键为 k 的元素移动到最靠前或者最靠后的位置(last 的默认值是 True)
d.__reversed__() 返回倒序的键的迭代器
  • default_factory 并不是一个方法, 而是一个可调用对象( callable) , 它的值在defaultdict 初始化的时候由用户设定。

相同方法

方法 说明
d.clear() 移除所有元素
d.__contains__(k) 检查 k 是否在 d 中
d.copy() 浅复制
d.fromkeys(it,[initial]) 将迭代器 it 里的元素设置为映射里的键, 如果有 initial 参数,
就把它作为这些键对应的值(默认是 None)
d.get(k,[default]) 没有键 k, 则返回 None 或者default
d.items() 返回 d 里所有的键值对
d.__iter__() 获取键的迭代器
d.keys() 获取所有的键
d.pop(k, [defaul]) 返回键 k 所对应的值, 然后移除这个键值对。 如果没有这
个键,返回 None 或者 defaul
d.popitem() 随机返回一个键值对并从字典里移除它
d.setdefault(k,[default]) 若字典里有键k, 则把它对应的值设置为 default,
然后返回这个值; 若无, 则让 d[k] =default, 然后返回 default
d.update(m,[**kargs]) m 可以是映射或者键值对迭代器, 用来更新 d 里对应的条目
d.values() 返回字典里的所有值
  • OrderedDict.popitem() 会移除字典里最先插入的元素( 先进先出) ; 同时这个方法还有一个可选的 last 参数, 若为真, 则会移除最后插入的元素( 后进先出) 。

用setdefault处理找不到的键 (用于更新操作)

当字典 d[k] 不能找到正确的键的时候, Python 会抛出异常, 这个行为符合 Python 所信奉的“快速失败”哲学。

            
              my_dict
              
                .
              
              setdefault
              
                (
              
              key
              
                ,
              
              
                [
              
              
                ]
              
              
                )
              
              
                .
              
              append
              
                (
              
              new_value
              
                )
              
              
                # 跟这样写
              
              
                if
              
               key 
              
                not
              
              
                in
              
               my_dict
              
                :
              
              
	my_dict
              
                [
              
              key
              
                ]
              
              
                =
              
              
                [
              
              
                ]
              
              
my_dict
              
                [
              
              key
              
                ]
              
              
                .
              
              append
              
                (
              
              new_value
              
                )
              
              
                #二者的效果是一样的,只不过后者至少要进行两次键查询——如果键不存在的话,就是三次,用 setdefault 只需要一次就可以完成整个操作
              
            
          

映射的弹性键查询

有时候为了方便起见, 就算某个键在映射里不存在, 我们也希望在通过这个键读取值的时候能得到一个默认值。

**defaultdict: 处理找不到的键的一个选择 **

在用户创建 defaultdict 对象的时候, 就需要给它配置一个为找不到的键创造默认值的方法。

            
              
                '''
比如,我们新建了这样一个字典:dd = defaultdict(list),如果键'new-key' 在 dd 中还不存在的话,表达式 dd['new-key'] 会按照以下的步骤来行事。
(1) 调用 list() 来建立一个新列表。
(2) 把这个新列表作为值, 'new-key' 作为它的键, 放到 dd 中。
(3) 返回这个列表的引用。
而这个用来生成默认值的可调用对象存放在名为 default_factory 的实例属性里。
'''
              
              
d 
              
                =
              
               collections
              
                .
              
              defaultdict
              
                (
              
              
                list
              
              
                )
              
              
                print
              
              
                (
              
              d
              
                .
              
              default_factory
              
                )
              
              
                # ==>
                
              
              
                print
              
              
                (
              
              d
              
                [
              
              
                'key'
              
              
                ]
              
              
                )
              
              
                # ==>[]
              
            
          
  • defaultdict 里的 default_factory 只会在 __getitem__ 里被调用, get(key) 则会返回 None。

特殊方法 __missing__

所有的映射类型在处理找不到的键的时候, 都会牵扯到 __missing__ 方法。 这也是这个方法称作“missing”的原因。 虽然基类 dict 并没有定义这个方法, 但是 dict 是知道有这么个东西存在的。

            
              
                # 在查询的时候把非字符串的键转换为字符串
              
              
                class
              
              
                StrKeyDict0
              
              
                (
              
              
                dict
              
              
                )
              
              
                :
              
              
                def
              
              
                __missing__
              
              
                (
              
              self
              
                ,
              
               key
              
                )
              
              
                :
              
              
                if
              
              
                isinstance
              
              
                (
              
              key
              
                ,
              
              
                str
              
              
                )
              
              
                :
              
              
                raise
              
               KeyError
              
                (
              
              key
              
                )
              
              
                return
              
               self
              
                [
              
              
                str
              
              
                (
              
              key
              
                )
              
              
                ]
              
              
                def
              
              
                get
              
              
                (
              
              self
              
                ,
              
               key
              
                ,
              
               default
              
                =
              
              
                None
              
              
                )
              
              
                :
              
              
                try
              
              
                :
              
              
                return
              
               self
              
                [
              
              key
              
                ]
              
              
                except
              
               KeyError
              
                :
              
              
                return
              
               default 

              
                def
              
              
                __contains__
              
              
                (
              
              self
              
                ,
              
               key
              
                )
              
              
                :
              
              
                return
              
               key 
              
                in
              
               self
              
                .
              
              keys
              
                (
              
              
                )
              
              
                or
              
              
                str
              
              
                (
              
              key
              
                )
              
              
                in
              
               self
              
                .
              
              keys
              
                (
              
              
                )
              
            
          
  • __missing__ 方法只会被 __getitem__ 调用(比如在表达式 d[k] 中)

  • k in my_dict.keys() 这种操作在 Python 3 中是很快的, 而且即便映射类型对象很庞大也没关系。 这是因为 dict.keys() 的返回值是一个“视图”。 视图就像一个集合, 而且跟字典类似的是, 在视图里查找一个元素的速度很快。

字典的变种

**collections.OrderedDict **

这个类型在添加键的时候会保持顺序, 因此键的迭代次序总是一致的。 OrderedDict 的 popitem 方法默认删除并返回的是字典里的最后一个元素, 但是如果像 my_odict.popitem(last=False) 这样调用它, 那么它删除并返回第一个被添加进去的元素。

**collections.ChainMap **

该类型可以容纳数个不同的映射对象, 然后在进行键查找操作的时候, 这些对象会被当作一个整体被逐个查找, 直到键被找到为止。 这个功能在给有嵌套作用域的语言做解释器的时候很有用, 可以用一个映射对象来代表一个作用域的上下文。

**collections.Counter **

这个映射类型会给键准备一个整数计数器。 每次更新一个键的时候都会增加这个计数器。 所以这个类型可以用来给可散列表对象计数, 或者是当成多重集来用——多重集合就是集合里的元素可以出现不止一次。 Counter 实现了 + 和 - 运算符用来合并记录, 还有像 most_common([n]) 这类很有用的方法。

            
              ct 
              
                =
              
               collections
              
                .
              
              Counter
              
                (
              
              
                'abracadabra'
              
              
                )
              
              
                # Counter({'a': 5, 'b': 2, 'r': 2, 'c': 1, 'd': 1})
              
              
ct
              
                .
              
              update
              
                (
              
              
                'aaaaazzz'
              
              
                )
              
              
                # Counter({'a': 10, 'z': 3, 'b': 2, 'r': 2, 'c': 1, 'd': 1})
              
              
ct
              
                .
              
              most_common
              
                (
              
              
                2
              
              
                )
              
              
                # [('a', 10), ('z', 3)]
              
            
          

**colllections.UserDict **

这个类其实就是把标准 dict 用纯 Python 又实现了一遍。跟 OrderedDict、 ChainMap 和 Counter 这些开箱即用的类型不同, UserDict 是让用户继承写子类的。而更倾向于从 UserDict 而不是从 dict 继承的主要原因是, 后者有时会在某些方法的实现上走一些捷径, 导致我们不得不在它的子类中重写这些方法, 但是 UserDict 就不会带来这些问题。

不可变映射类型

从 Python 3.3 开始, types 模块中引入了一个封装类名叫MappingProxyType。 如果给这个类一个映射, 它会返回一个只读的映射视图。 虽然是个只读视图, 但是它是动态的。 这意味着如果对原映射做出了改动, 我们通过这个视图可以观察到, 但是无法通过这个视图对原映射做出修改。

            
              d 
              
                =
              
              
                {
              
              
                1
              
              
                :
              
              
                'A'
              
              
                }
              
              
d_proxy 
              
                =
              
               MappingProxyType
              
                (
              
              d
              
                )
              
              
                print
              
              
                (
              
              d_proxy
              
                [
              
              
                1
              
              
                ]
              
              
                )
              
              
                # ==>A
              
              
                # 不可修改
              
              
d_proxy
              
                [
              
              
                2
              
              
                ]
              
              
                =
              
              
                'x'
              
              
                # TypeError: 'mappingproxy' object does not support item assignment
              
            
          

集合

“集”这个概念在 Python 中算是比较年轻的, 同时它的使用率也比较低。

集合 UML

01. Python3 数据类型(一)_第3张图片

set 和 frozenset

  • set无序排序且不重复,是可变的,有add(),remove()等方法。

  • frozenset是冻结的集合,它是不可变的,存在哈希值,好处是它可以作为字典的key,也可以作为其它集合的元素。缺点是一旦创建便不能更改,没有add,remove方法。

集合字面量

除空集之外, 集合的字面量——{1}、 {1, 2}, 等等——看起来跟它的数学形式一模一样。 如果是空集, 那么必须写成 set() 的形式。

  • 只是写成 {} 的形式, 跟以前一样, 你创建的其实是个空字典。

集合推导

            
              s 
              
                =
              
              
                {
              
              
                chr
              
              
                (
              
              i
              
                )
              
              
                for
              
               i 
              
                in
              
              
                range
              
              
                (
              
              
                32
              
              
                ,
              
              
                40
              
              
                )
              
              
                }
              
              
                # {'!', '#', '"', '$', '%', "'", ' ', '&'}
              
            
          

集合的操作

集合的数学运算

数学符号 Python运算符 描述
S ∩ Z s & z s 和 z 的交集
S ∪ Z s | z s 和 z 的并集
S - Z s - z s 和 z 的差集, 或者叫作相对补集
S △ Z s ^ z s 和 z 的对称差集

集合的比较运算符 :

数学符号 Python运算符 描述
e ∈ S e in s 元素 e 是否属于 s
S ⊆ Z s <= z s 是否为 z 的子集
S ⊂ Z s < z s 是否为 z 的真子集
S ⊇ Z s >= z s 是否为 z 的父集
S ⊃ Z s > z s 是否为 z 的真父集

dict和set的背后

想要理解 Python 里字典和集合类型的长处和弱点, 它们背后的散列表是绕不开的一环。

dict的实现及其导致的结果

  • 键必须是可散列的

    • 支持 hash() 函数, 并且通过 __hash__() 方法所得到的散列值是不变的。
    • 支持通过 __eq__() 方法来检测相等性。
    • a == b 为真, 则 hash(a) == hash(b) 也为真。
  • 字典在内存上的开销巨大

    • 字典使用了散列表, 而散列表又必须是稀疏的, 这导致它在空间上的效率低下。
    • 如果需要存放数量巨大的记录, 那么放在由元组或是具名元组构成的列表中会是比较好的选择 。
  • 键查询很快

    • dict 的实现是典型的空间换时间: 字典类型有着巨大的内存开销, 但它们提供了无视数据量大小的快速访问——只要字典能被装在内存里。
  • 键的次序取决于添加顺序

    • 往 dict 里添加新键而又发生散列冲突的时候, 新键可能会被安排存放到另一个位置。
  • 往字典里添加新键可能会改变已有键的顺序

    • 无论何时往字典里添加新的键, Python 解释器都可能做出为字典扩容的决定。 这个过程中可能会发生新的散列冲突, 导致新散列表中键的次序变化。

ps: 在 Python 3 中, .keys()、 .items() 和 .values() 方法返回的都是字典视图。

set的实现以及导致的结果

set 和 frozenset 的实现也依赖散列表, 但在它们的散列表里存放的只有元素的引用 。

上面所提到的字典和散列表的几个特点, 对集合来说几乎都是适用的。

  • 集合里的元素必须是可散列的。
  • 集合很消耗内存。
  • 可以很高效地判断元素是否存在于某个集合。
  • 元素的次序取决于被添加到集合里的次序。
  • 往集合里添加元素, 可能会改变集合里已有元素的次序。

更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论