Python指南:组合数据类型

本章我们将学习如何使用Python的组合数据类型将数据项集合在一起,以便在程序设计时有更多的选项。

组合数据类型

1、序列类型

Python提供了5中内置的序列类型:bytearraybytesliststrtuple,序列类型支持成员关系操作符(in)、大小计算函数(len())、分片([]),并且是可可迭代的。

1.1 元组

元组是个有序序列,包含0个或多个对象引用,使用小括号包裹。元组是固定的,不能替换或删除其中包含的任意数据项。

1.1.1 元组的创建

使用()创建一个元组:

括号内不包含内容,则创建一个空元组

括号内包含使用逗号分隔的数据项,创建一个非空元组

也可以使用tuple()创建一个元组:

不指定参数时,返回一个空元组

使用tuple作为参数时,返回该参数的浅拷贝

其他参数时,尝试将给定的对象转换为tuple类型

1.1.2 元组索引和分片

1.1.3 元组方法

元组只提供两种方法:

1.1.4 元组运算符

与字符串一样,元组之间可以使用 + 号和 * 号进行运算。这就意味着他们可以组合和复制,运算后会生成一个新的元组。

1.1.5 元组的删除

元组中的元素值是不允许删除的,但我们可以使用del删除整个元组:

1.1.6 无关闭分隔符

当元组出现在二进制操作符的左边或出现在unary语句的右边时,可以不使用圆括号。

1.2 命名的元组

命名的元组(namedtuple)与普通元组一样,有相同的表现特征,其添加的功能就是可以根据名称引用元组中的项

collections模块提供了namedtuple()函数,用于创建自定义的元组数据类型。该函数的第一个参数是想要创建的自定义元组数据类型的名称,第二个参数是一个字符串,其中包含使用空格分隔的名称,每个名称代表该元祖数据类型中的一项。该函数返回一个自定义的类,可用于创建命名的元组。

这里我们创建了包含两个Sale项的列表,我们可以使用索引位置来引用元组中的项,也可以使用名称进行引用,后者正式命名的元组的特点:

1.3 列表

列表是包含0个或多个对象引用的有序序列,支持与字符串以及元组一样的分片与步距语法,列表是可变的,因此我们可以对列表中的项进行删除或替换,插入、替换或删除列表中的分片也是可能的。

1.3.1 列表的创建

使用[]创建一个元组:

括号内不包含内容,则创建一个空列表

括号内包含使用逗号分隔的数据项,创建一个非空列表

也可以使用list()创建一个列表:

不指定参数时,返回一个空列表

使用list作为参数时,返回该参数的浅拷贝

其他参数时,尝试将给定的对象转换为list类型

1.3.2 列表索引和分片

1.3.3 列表方法

下表中,L为列表。

1.3.4 拆分操作符

任意可迭代的(列表、元组等)数据类型都可以使用序列拆分操作符进行拆分,即*。用于赋值操作符左边的两个或多个变量时,其中一个使用*进行引导,数据项将赋值给该变量,而所有剩下的数据项将给带星号的变量。

1.3.5 删除

由于列表是可变的,我们可以对其数据项进行删除。

删除单个数据项

删除分片

1.3.6 列表内涵

列表内涵是一个表达式,也是一个循环,该循环有一个可选的、包含在方括号中的条件,作用是为列表生成数据项,并且可以使用条件过滤掉不需要的数据项,可以使用表达式,也可以使用附加条件。常见语法:

[expression for item in iterable]

[expression for item in iterable if condition]

在没有列表内涵时,我们找出1900~1940年之间所有的闰年,可能会这么写:

学习了列表内涵之后我们可以简化程序:

两种方法等效,得到同样的结果。

2、集合类型

set也是一种组合数据类型,支持成员关系操作符(in)、对象大小计算操作符(len()),并且也是iterable。Python提供了两种内置的集合类型:可变的set类型,固定的frozenset类型。进行迭代时,集合类型以任意顺序提供其数据项。

只有可哈希运算的对象可以添加到集合中。所有的内置固定数据类型(比如float、frozenset、int、str、tuple)都是可哈希运算的,可以添加到集合中。内置的可变数据类型(比如dict、list、set)都不是可哈希运算的,不能添加到集合中。

2.1 集合

集合是0个或多个对象引用的无序组合。集合是可变的,因此可以很容易的添加和移除数据项,但是由于其中的项是无序的,因此没有索引位置的概念,也不能分片或按步距分片。

2.1.1 集合的创建

使用set()创建一个集合:

不指定参数时,返回一个空集合

使用set作为参数时,返回该参数的浅拷贝

其他参数时,尝试将给定的对象转换为集合

集合中包含的每个数据项都是独一无二的——添加重复的数据项固然不会引发问题,但是也毫无意义。比如,下面产生的三个集合是一样的:set('apple')、set('aple')、{‘e', 'p', 'l', 'a'}。鉴于此,集合常用于删除重复的数据项。比如,x是一个字符串列表,在执行之后,x中的每个字符串都是独一无二的,存放顺序是任意的。

2.1.2 集合方法与操作符

s、t为集合,x为数据项。

2.1.3 集合内涵

除了调用set()创建集合,或使用集合字面值创建集合外,我们可以使用集合内涵创建集合。集合内涵是一个表达式,也是一个带有可选条件的循环,支持的语法:

2.2 固定集合

固定集合是指那种一旦创建就不能修改的集合,只能使用frozenset数据类型函数创建,不带参数调用时,frozenset()返回一个空的固定集合,带一个frozenset参数时,将返回改参数的 浅拷贝,对于任何其他类型的参数,都尝试将给定的对象转换为一个forzenset。

3、映射类型

映射是键-值数据项的组合,并提供了存取数据项及其键、值的方法。Python3.0支持两种无序的映射类型——内置的dict类型以及标准库中的collections.defaultdict类型。Python3.1引入了一种新的、有序的映射类型collections.OrderedDict,该类型是一个字典,与内置的dict有相同的方法和属性,但在存储数据项时以插入顺序进行。

3.1 字典

dict是一种无序的组合数据类型,其中包含0个或多个键-值对。

3.1.1 字典的创建

可以使用{}创建:

空的花括号创建一个空的字典

包含一个或多个逗号分隔的键值对,创建一个非空字典

也可以使用dict()函数创建:

不带参数,创建一个空的字典

带有dict类型的参数,返回该参数的浅拷贝

键值对组合的参数,创建非空字典

字典的键值是独一无二的,因此,如果向字典中添加一个已存在的键值项,实际效果是新值替换旧值。

3.1.2 字典方法

d为字典

上面提到了“视图”概念,其相对于通常的iterables有两个不同点:

如果该视图引用的字典发生变化,那么视图将反映该变化。

键视图与项视图支持一些类似于集合的操作:

v & x # Intersection

v | x # Union

v - x # Difference

v ^ x # Symmentric difference

注:两种通过键取值方式的比较

我们可以通过d[k]d.get()两种形式来取值,比如我们进行词频统计时,使用words[word]+=1words[word] = words.get(word, 0) + 1都可以进行加1操作,但是如果单词第一次出现,第一种形式会产生KeyValue错误,第二种则会正确运行。

3.1.3 字典内涵

字典内涵是一个表达式,也是一个循环,该循环带有一个可选条件。语法:

例:

3.2 默认字典

默认字典也是一种字典——这种字典包含普通字典所提供的所有操作符与方法,与其不同的是可以对遗失的键进行处理

创建默认字典时,我们可以传入一个工厂函数,这样就会为遗失的键创建默认值。看下面例子

上面我们创建的默认字典words永远不会产生KeyError异常,如果遇到没有的键,其值通过工厂函数(int())设置为0。

3.3 有序字典

有序字典collections.OrderedDict是以数据项的插入顺序进行存储。

可以看出我们通过二元组列表创建有序字典后,获取去键视图也为有序的。

有序字典另一种稍专业一些的用途是生成排序字典。给定一个字典d,可以按如下方式转换为排序字典:。

4、组合数据类型的迭代与复制

4.1 迭代子、迭代操作与函数

iterable数据类型每次返回其中的一个数据项。任意包含__iter__() 方法的对象或任意序列(也即包含__getitem__()方法的对象)都是一个iterable,并可以提供一个迭代子。迭代子是一个对象,该对象可以提供__next__()方法,该方法依次返回每个相继的数据项,并在没有数据项时产生StopIteration异常。

常见的迭代操作符与函数(s与t为序列):

数据项返回的顺序依赖于底层的iterable。对列表和元组等情况,数据项的返回值通常从第一个数据项开始依次返回,而对于字典与集合,迭代子是任意顺序的返回项。

4.2 组合类型的复制

由于数据片总是曲子某个数据项的一个单独副本,所以获取一个列表的副本可以通过下面方式:

对于字典和集合,可以使用dict.copy()set.copy()来实现。此外,copy模块还提供了copy.copy()函数,该函数返回给定对象的一个副本。

在以上各种组合数据类型创建的时候,提到可以使用工厂方法来创建一个组合数据类型的副本:

注意:以上的复制都是浅拷贝,也就是说,复制的知识对象引用而非对象本身。对于固定数据类型(数字、字符串等),这与复制的效果是相同的,但对于可变的数据类型,比如嵌套的组合类型,这意味着相关对象同时被原来的组合与复制得来的组合引用。请看下面代码:

从输出结果可以看出,前两项固定数据类型并没有同时改变,而列表中的列表同时变化,说明x与y的第三项都指向的同一列表的引用。我们可以使用深拷贝来避免此类问题:

从输出结果看,x与y已经完全独立了。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180412G1QJAK00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券