07-数据结构

数据容器(数据结构)

前面咱们介绍了 Python 最底层的基本数据类型:布尔型整型浮点型以及字符串型html

本章将要提到的 数据结构(容器) 。在这一章中,咱们会把以前所学的基本 Python 类型以更为复杂的方式组织起来。这些数据结构之后会常常用到。在编程中,最多见的工做就是将数据进行拆分或合并,将其加工为特定的形式python

大多数编程语言都有特定的数据结构来存储由一系列元素组成的序列,这些元素以它们所处的位置为索引:从第一个到最后一个依次编号。前一章已经见过 Python 字符串了,它本质上是字符组成的序列。编程

本文内容

  • 列表
  • 元组
  • 字典
  • 集合

知识点回顾

  • Python 中数据类型能够分为 数字型非数字型
  • 数字型
    • 整型 (int)
    • 浮点型(float
    • 布尔型(bool
      • True 非 0 数 —— 非零即真
      • False 0
  • 非数字型
    • 字符串
  • Python 中,全部 非数字型变量 都支持如下特色:
    1. 都是一个 序列 sequence,也能够理解为 容器
    2. 取值 []
    3. 遍历 for in
    4. 连接 +重复 *
    5. 切片

列表(list)

列表是最多见的一种数据形式,是一种 有序序列 ,能够随时添加和删除其中的元素。数组

列表很是适合利用顺序和位置定位某一元素,尤为是当元素的顺序或内容常常发生改变时。与字符串不一样,列表是可变的。你能够直接对原始列表进行修改:添加新元素、删除或覆盖已有元素。安全

列表建立

  • List(列表) 是 Python 中使用 最频繁 的数据类型,在其余语言中一般叫作 数组
  • 专门用于存储 一串 信息
  • 列表用 [] 定义,数据 之间使用 , 分隔
  • 列表的 索引0 开始
    • 索引 就是数据在 列表 中的位置编号,索引 又能够被称为 下标

注意:从列表中取值时,若是 超出索引范围,程序会报错数据结构

# 用 list 建立空列表
array = list()
array
# 用 [] 建立空列表
array2 = []
array2

建立一个列表app

array3 = [1, 2, 3, 4, 5, 6, 7]
array3

# 列表中能够存放多种数据
array4 = [1, 2, 3, True, False, int, "str", array]
array

类型转化

# 使用list()将其余数据类型转换成列表
s = 'hello world !'
list(s)

['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', ' ', '!']

列表取值

使用[offset]获取与修改元素编程语言

# 直接获取
s[0]

s[-1]

根据索引位置修改内容函数

array3[0] = 5

列表切片

切片是返回一个新的内容this

Python中符合序列的有序序列都支持切片(slice),例如列表,字符串,元组。

格式:[start:stop:step]

[起始值:结束值:步长]

  • start: 起始索引,从0开始,-1表示结束
  • stop:结束索引
  • step:步长,end-start,步长为正时,从左向右取值。步长为负时,反向取值
arr = list(range(10))

# 指定区间切片
arr[0:5]

# 从头开始切片
arr[0:5]

# 切片到末尾
arr[0:]

# 省略参数切所有内容
arr[:]

# 逆序切片
arr[-12:-7]

# 指定步长切片
arr[0:5:1]
arr[0:5:2]

列表经常使用操做

  • ipython 中定义一个 列表,例如:l= list()
  • 输入 l. 按下 TAB 键, ipython 会提示 列表 可以使用的函数以下:
append()  count()   insert()  reverse()
clear()   extend()  pop()     sort()
copy()    index()   remove()

在变量后面输入 .,而后选择针对这个变量要执行的操做,记忆起来比函数要简单不少

分类 关键字 / 函数 / 方法 说明
增长 append() 添加元素至尾部
insert() 在指定位置插入数据
删除 clear() 清空列表
pop() 默认弹出末尾数据
pop(index) 弹出指定索引数据
remove(data) 移除指定数据
修改 extend(列表2) 将列表2 的数据追加到列表
查询 count(数据) 统计数据出现的次数
index(内容) 查询内容所在位置
其余 copy() 将列表复制一份
sort() 排序
reverse() 逆序列表

案例:

In [7]: arr = list(range(1, 5))

# 添加元素到末尾
In [8]: arr.append(5)

In [9]: arr
Out[9]: [1, 2, 3, 4, 5]
# 插入元素到第一个
In [10]: arr.insert(0, 0)

In [11]: arr
Out[11]: [0, 1, 2, 3, 4, 5]
# 默认弹出最后一个元素
In [12]: arr.pop()
Out[12]: 5
# 指定弹出第一个元素
In [13]: arr.pop(0)
Out[13]: 0

In [14]: arr
Out[14]: [1, 2, 3, 4]
# 指定删除内容为 4 的元素
In [15]: arr.remove(4)

In [16]: arr
Out[16]: [1, 2, 3]
# 合并[4, 5, 6]列表
In [17]: arr.extend([4,5,6])

In [18]: arr
Out[18]: [1, 2, 3, 4, 5, 6]
# 查询内容为 4 的元素在第几个位置
In [19]: arr.index(4)
Out[19]: 3
# 排序后将内容输出(默认为升序)
In [20]: arr.sort(reverse=True)

In [21]: arr
Out[21]: [6, 5, 4, 3, 2, 1]
# 排序后将内容输出
In [22]: arr.sort()

In [23]: arr
Out[23]: [1, 2, 3, 4, 5, 6]

其余用方法

  • 使用in判断值是否存在
  • 使用 += 合并列表
  • 使用 len() 获取长度
  • 使用join()转换为字符串
In [24]: 2 in arr
Out[24]: True

In [25]: arr + [7,8,9]
Out[25]: [1, 2, 3, 4, 5, 6, 7, 8, 9]

In [26]: arr
Out[26]: [1, 2, 3, 4, 5, 6]

In [27]: len(arr)
Out[27]: 6

案例:

l = ['a', 'b', 1, 2, 3, 'c', 'd']
"""
打印将列表前两位与后两位删除的列表
打印将列表第三到第六位之间删除内容

"""

列表推导式(简单介绍)

推导式comprehensions(又称解析式),是Python的一种独有特性。推导式是能够从一个数据序列构建另外一个新的数据序列的结构体。

x = []
for i in range(1,11):
	x.append(i)


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

对象引用、浅拷贝、深拷贝(拓展、难点、重点)

使用=赋值(对象引用)

>>> a = [1, 2, 3]
>>> a
[1, 2, 3]
>>> b = a
>>> b
[1, 2, 3]
>>> a[0] = 'surprise'
>>> a
['surprise', 2, 3]

>>> b
['surprise', 2, 3]
>>> b[0] = 'I hate surprises'
>>> b
['I hate surprises', 2, 3]
>>> a
['I hate surprises', 2, 3]

浅拷贝(copy)

>>> a = [1, 2, 3]
>>> b = a.copy()
>>> c = list(a)
>>> d = a[:]

>>> a[0] = 'integer lists are boring'
>>> a
['integer lists are boring', 2, 3]
>>> b
[1, 2, 3]
>>> c
[1, 2, 3]
>>> d
[1, 2, 3]

深拷贝(deepcopy)

>>> import copy
>>> a = [1, 2, 3, [1, 2, 3]]
>>> b = copy.copy(a)
>>> a[3][0] = "surprises"
>>> b
[1, 2, 3, ['surprises', 2, 3]]

>>> c = copy.deepcopy(b)
>>> b[3][0] = "i hate surprises"
>>> c
[1, 2, 3, ['surprises', 2, 3]]
>>> b
[1, 2, 3, ['i hate surprises', 2, 3]]

总结:

copy.copy 浅拷贝 只拷贝父对象,不会拷贝对象的内部的子对象。
copy.deepcopy 深拷贝 拷贝对象及其子对象

元组

建立元组

  • 元组和列表相似,但属于不可变序列元组一旦建立,用任何方法都不能够修改其元素
  • 元组的定义方式和列表相同,但定义时全部元素是放在一对圆括号“()”中,而不是方括号中。
  • 元组没有列表中那么多方法可使用,由于不可变,因此安全,速度比列表快。
# 使用 tuple() 建立元组
>>>tuple()
()

# 使用 () 建立元组
>>> ()
()

>>> type(())
tuple
>>> type(tuple())
tuple

元组中只包含一个元素时,须要在元素后面添加逗号

info_tuple = (50, )

元组取值与切片

  • 元组的取值、切片与列表时同样使用
  • 不能对元组的元素进行删除,可是能够删除整个元组:
In [1]: t = tuple("01234")

In [2]: t
Out[2]: ('0', '1', '2', '3', '4')

# 直接获取
In [3]: t[0]
Out[3]: '0'

In [4]: t[-1]
Out[4]: '4'
# 不能修改
In [5]: t[0] = 1
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-5-c8aeb8cd20ae> in <module>
----> 1 t[0] = 1

TypeError: 'tuple' object does not support item assignment

In [6]: t[0:5]
Out[6]: ('0', '1', '2', '3', '4')

元组经常使用操做

  • ipython 中定义一个 元组,例如:info = ()
  • 输入 info. 按下 TAB 键,ipython 会提示 元组 可以使用的函数以下:
info.count  info.index

循环遍历

  • 取值 就是从 元组 中获取存储在指定位置的数据
  • 遍历 就是 从头至尾 依次元组 中获取数据
# for 循环内部使用的变量 in 元组
for item in info:
    # 循环内部针对元组元素进行操做
    print(item)
  • Python 中,可使用 for 循环遍历全部非数字型类型的变量:列表元组字典 以及 字符串

元组和列表之间的转换

  • 使用 list 函数能够把元组转换成列表
list(元组)
  • 使用 tuple 函数能够把列表转换成元组
tuple(列表)

元组解包

序列类型

In [7]: a, b, c = tuple('abc')

In [8]: a
Out[8]: 'a'

In [9]: b
Out[9]: 'b'

In [10]: c
Out[10]: 'c'
    
# 用 _ 收集不用的元组
In [15]: _, _, c = tuple('abc')

In [16]: c
Out[16]: 'c'

_ 是被舍弃的变量

元组与列表的区别

  • 元组一旦定义就不容许更改。
  • 元组没有append()extend()insert()等方法,没法向元组中添加元素。
  • 元组没有remove()pop()方法,也没法对元组元素进行del操做,不能从元组中删除元素。
  • 从效果上看,tuple( )冻结列表,而list( )融化元组。

元组的优势

  • 元组的速度比列表更快。若是定义了一系列常量值,而所需作的仅是对它进行遍历,那么通常使用元组而不用列表。
  • 元组对不须要改变的数据进行 “写保护” 将使得代码更加安全
  • 元组可用做字典的“键”,也能够做为集合的元素列表永远不能当作字典键使用,也不能做为集合的元素,由于列表不是不可变的。

元组的缺点

不可修改

集合(set)

集合是无序可变序列,使用一对大括号界定,元素不可重复,同一个集合中每一个元素都是惟一的。

集合中只能包含数字、字符串、元组等不可变类型(或者说可哈希)的数据,而不能包含列表、字典、集合等可变类型的数据。

注意:建立一个空集合必须用 set() 而不是 { },由于 { } 是用来建立一个空字典。

集合的建立与删除

直接将集合赋值给变量

>>> a = {3, 5}
>>> a.add(7)                  #向集合中添加元素
>>> a
{3, 5, 7}

使用set将其余类型数据转换为集合

>>> a_set = set(range(8,14))
>>> a_set
{8, 9, 10, 11, 12, 13}
>>> b_set = set([0, 1, 2, 3, 0, 1, 2, 3, 7, 8])   #自动去除重复
>>> b_set
{0, 1, 2, 3, 7, 8}
>>> c_set = set()                                 #空集合
>>> c_set
set()

集合运算

In [4]: a = {1, 2}

In [5]: b = {2, 3}

In [6]: a & b
Out[6]: {2}

In [7]: a.intersection(b)
Out[7]: {2}

In [8]: a | b
Out[8]: {1, 2, 3}

In [9]: a.union(b)
Out[9]: {1, 2, 3}

In [10]: a - b
Out[10]: {1}

In [11]: a.difference(b)
Out[11]: {1}

字典(dict)(无序)

字典(dictionary)是一种 key-value(键值对) 数据类型,且可存储任意类型对象。

字典的每一个键值(key=>value)对用冒号(:)分割,每一个对之间用逗号(,)分割,整个字典包括在花括号({})中

  • 字典是无序可变
  • 定义字典时,每一个元素的键和值用冒号分隔,元素之间用逗号分隔,全部的元素放在一对大括号“{}”中。
  • 字典中的 键能够为任意不可变数据 ,好比整数、实数、复数、字符串、元组等等。

字典的定义

  • 字典用 {} 定义
  • 字典使用 键值对 存储数据,键值对之间使用 , 分隔
    • key 是索引
    • value 是数据
    • 之间使用 : 分隔
    • 键必须是惟一的
    • 能够取任何数据类型,但 只能使用 字符串数字元组

字典的建立与修改

使用 {} 或者 dict() 建立空字典

In [1]: {}
Out[1]: {}

In [2]: dict()
Out[2]: {}

In [3]: type({})
Out[3]: dict

In [4]: type(dict())
Out[4]: dict

建立简单的字典

In [24]: d = {"name":"张三"}

In [25]: d
Out[25]: {'name': '张三'}
# 根据键名取值
In [26]: d['name']
Out[26]: '张三'

指定键名修改字典内容

In [34]: d['name'] = '李四'

In [35]: d
Out[35]: {'name': '李四'}
    
# 以键做为下标能够读取字典元素,若键不存在则抛出异常
In [14]: d['name1']                     #键不存在,抛出异常
------------------------------------------
KeyError                Traceback (most recent call last)
<ipython-input-17-688f57ecfd16> in <module>()
----> 1 d['name1']

KeyError: 'name1'
    
# 给不存在的键赋值添加内容
In [36]: d['name1'] = '张三'

In [37]: d
Out[37]: {'name': '李四', 'name1': '张三'}

建立复杂字典

字典与列表相似,能够存听任意类型的值。字典中每一个元素拥有与之对应的互不相同的键(key),须要经过键来访问元素。

键一般是字符串,但它还能够是 Python 中其余任意的不可变类型:布尔型、整型、浮点型、元组、字符串,以及其余一些在后面的内容中会见到的类型。字典是可变的,所以你能够增长、删除或修改其中的键值对。

键不能够重复。

In [7]: d = {'str':'马克',
   ...:      'int':18,
   ...:      'bool':True,
   ...:      'list':[1, 2, 3],
   ...:      'tuple':(1, 2, 3),
   ...:      'set':{1, 2, 3},
   ...:      'dict':{
   ...:          'str':'马克',
   ...:          'int':18
   ...:      }
   ...:  }

In [8]: d
Out[8]:
{'str': '马克',
 'int': 18,
 'bool': True,
 'list': [1, 2, 3],
 'tuple': (1, 2, 3),
 'set': {1, 2, 3},
 'dict': {'str': '马克', 'int': 18}}

课后能够作一个练习:本身定义一个字典数据格式

字典元素添加与修改

  • 当以指定键为下标为字典赋值时:
    1. 若键存在,则能够修改该键的值;
    2. 若不存在,则表示添加一个键、值对。
In [15]: d["new"] = 'new' # 添加内容

In [16]: d
Out[16]:
{'str': '马克',
 'int': 18,
 'bool': True,
 'list': [1, 2, 3],
 'tuple': (1, 2, 3),
 'set': {1, 2, 3},
 'dict': {'str': '马克', 'int': 18},
 'new': 'new'}

In [18]: d["new"] = '新元素'

In [19]: d
Out[19]:
{'str': '马克',
 'int': 18,
 'bool': True,
 'list': [1, 2, 3],
 'tuple': (1, 2, 3),
 'set': {1, 2, 3},
 'dict': {'str': '马克', 'int': 18},
 'new': '新元素'}

字典经常使用方法

  • ipython 中定义一个 字典,例如:d= {}
  • 输入 d. 按下 TAB 键,ipython 会提示 字典 可以使用的函数以下:
In [1]: d.
clear()      get()        pop()        update()
copy()       items()      popitem()    values()
fromkeys()   keys()       setdefault()
方法名 做用
get() 根据 key 获取 value, 若是不存在,默认为空
keys() 获取全部 key 的列表
values() 获取全部 value的列表
items() 获取全部 (key, value) 的元组列表
update() dict1.update(dict2) 将字典2合并到字典1
copy() 复制一个字典
pop() dict1.pop(key) 指定 key 弹出 value
popitem() 随机弹出一对键值对
setdefault() dict1.setdefault(key, value)key 存在不修改数据。不存在新建键值对。
clear() 清空字典
del 使用del删除字典中指定键的元素

使用 get() 根据键名获取值

使用字典对象的get方法获取指定键对应的值,而且能够在键不存在的时候返回指定值。

In [39]: d
Out[39]:
{'str': '马克',
 'int': 18,
 'bool': True,
 'list': [1, 2, 3],
 'tuple': (1, 2, 3),
 'set': {1, 2, 3}}

In [40]: d.get('str1', "没有str1这个内容")
Out[40]: '没有str1这个内容'

使用 items() 方法获取字典的键、值对

In [41]: d.items()
Out[41]: dict_items([('str', '马克'), ('int', 18), ('bool', True), ('list', [1, 2, 3]), ('tuple', (1, 2, 3)), ('set', {1, 2, 3})])

使用 keys() 方法获取字典的键

In [42]: d.keys()
Out[42]: dict_keys(['str', 'int', 'bool', 'list', 'tuple', 'set'])

使用 values() 方法获取字典的值

In [43]: d.values()
Out[43]: dict_values(['马克', 18, True, [1, 2, 3], (1, 2, 3), {1, 2, 3}])

字典能够用来 存储多个数据

  • 一般用于存储 描述一个 物体 的相关信息

和列表的区别

  • 列表有序 的对象集合
  • 字典无序 的对象集合

循环遍历

  • 遍历 就是 依次字典 中获取全部键值对
# for 循环内部使用的 `key 的变量` in 字典
for k in d:

    print("%s: %s" % (k, xiaoming[k]))

提示:在实际开发中,因为字典中每个键值对保存数据的类型是不一样的,因此针对字典的循环遍历需求并非不少

应用场景

  • 尽管可使用 for in 遍历 字典
  • 可是在开发中,更多的应用场景是:
    • 使用 多个键值对,存储 描述一个 物体 的相关信息 —— 描述更复杂的数据信息
    • 多个字典 放在 一个列表 中,再进行遍历,在循环体内部针对每个字典进行 相同的处理
card_list = [{"name": "张三",
              "qq": "12345",
              "phone": "110"},
             {"name": "李四",
              "qq": "54321",
              "phone": "10086"}
             ]

案例:统计字符串中每一个字母出现的次数

d["name"] = 1

worlds = "this is a python and Python"

# 先建立一个空字典用于收集数据
worlds_dict = {}
for world in worlds:
    # 若是单词已经出如今字典中就 +1
    if world in worlds_dict:
        worlds_dict[world] = worlds_dict[world] + 1
    else:
        # 若是不存在字典中 就设置为1
        worlds_dict[world] = 1

print(worlds_dict.items())

for k,v in worlds_dict.items():
    print('单词:{} 出现了 {} 次'.format(k, v))

升级:

  • 不区分大小写统计
  • 统计以后排序输出

案例升级:

# -*- coding: utf-8 -*-
# https://docs.python.org/3/library/stdtypes.html#iterator-types
with open('iterator.txt', encoding='utf-8') as f:
    w = f.read()

worlds = w.split()
# 先建立一个空字典用于收集数据
worlds_dict = {}
for world in worlds:
    # 若是单词已经出如今字典中就 +1
    if world in worlds_dict:
        worlds_dict[world] = worlds_dict[world] + 1
    else:
        # 若是不存在字典中 就设置为1
        worlds_dict[world] = 1

worlds_dict = worlds_dict.items()
worlds_dict = sorted(worlds_dict, key=lambda x:x[1],reverse=True)
print(worlds_dict)

数据类型转化

int、float、str能够相互转化

In [1]: str(1)
Out[1]: '1'

In [2]: int('1')
Out[2]: 1

In [3]: float('1')
Out[3]: 1.0

# int关键字不能转为数字的字符串
In [4]: int("s")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-4-61f7ab14298a> in <module>()
----> 1 int("s")

ValueError: invalid literal for int() with base 10: 's'

str、list、tuple、set能够相互转化

# 字符串与列相互转化须要使用高级方法(显示转化)
In [6]: '1,2,3,4,5'.split(',')
Out[6]: ['1', '2', '3', '4', '5']

In [7]: ','.join(['1', '2', '3', '4', '5'])
Out[7]: '1,2,3,4,5'
# 数字类型不能直接转化为字符串
In [8]: ','.join([1, 2, 3, 4, 5])
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-8-16dd7015be3c> in <module>()
----> 1 ','.join([1, 2, 3, 4, 5])

TypeError: sequence item 0: expected str instance, int found

# list、tuple、set之间能够相互进行转化
In [9]: l = [1, 2, 3, 4, 5]

In [10]: tuple(l)
Out[10]: (1, 2, 3, 4, 5)

In [11]: set(l)
Out[11]: {1, 2, 3, 4, 5}

如下几个内置的函数能够执行数据类型之间的转换。这些函数返回一个新的对象,表示转换的值。Python Number 类型转换

关键字 说明
int(x [,base ]) 将 x 转换为一个整数
float(x ) 将 x 转换到一个浮点数
str(x ) 将对象 x 转换为字符串
tuple(s ) 将序列 s 转换为一个元组
list(s ) 将序列 s 转换为一个列表
set(s ) 将序列 s 转换为一个集合

序列解包

可使用序列解包功能对多个变量同时赋值

>>> x, y, z = 1, 2, 3             #多个变量同时赋值
>>> t = (False, 3.5, 'exp')
>>> (x, y, z) = t
>>> x, y, z = t
>>> x, y, z = range(3)            #能够对range对象进行序列解包
>>> a, b = b, a                   #交换两个变量的值
>>> a, b, c = 'ABC'               #字符串也支持序列解包
>>> x = [1, 2, 3, 4, 5, 6]
>>> x[:3] = map(str, range(5))    #切片也支持序列解包
>>> x
['0', '1', '2', '3', '4', 4, 5, 6]
  • 序列解包对于列表和字典一样有效
>>> s = {'a':1, 'b':2, 'c':3}
>>> b, c, d = s.items()
>>> b
('c', 3)
>>> b, c, d = s                #使用字典时不用太多考虑元素的顺序
>>> b
'c'
>>> b, c, d = s.values()
>>> print(b, c, d)
1 3 2
  • 序列解包遍历多个序列
>>> keys = ['a', 'b', 'c', 'd']
>>> values = [1, 2, 3, 4]
>>> for k, v in zip(keys, values):
	  print((k, v), end=' ')

('a', 1) ('b', 2) ('c', 3) ('d', 4)
  • Python 3.5还支持下面用法的序列解包
>>> print(*[1, 2, 3], 4, *(5, 6))
1 2 3 4 5 6
>>> *range(4),4
(0, 1, 2, 3, 4)
>>> [*range(10)]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> {'x': 1, **{'y': 2}}
{'y': 2, 'x': 1}
相关文章
相关标签/搜索