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}
相關文章
相關標籤/搜索