天天看點

2020.7.30 Python basic syntax05-字典、集合及序列

字典、集合及序列

    • 字典
      • 可變類型與不可變類型
      • 建立字典的幾種方法
      • 内置BIF
      • 課後習題
    • 集合
      • 集合的建立
      • 集合的内置方法
      • 不可變集合
    • 序列
      • Iterable對象的說明和相關内置函數

字典

可變類型與不可變類型

  • 序列是以連續的整數為索引,與此不同的是,字典以"關鍵字"為索引,關鍵字可以是任意不可變類型,通常用字元串或數值。
  • 字典是 Python 唯一的一個 映射類型,字元串、元組、清單屬于序列類型。

那麼如何快速判斷一個資料類型

X

是不是可變類型的呢?兩種方法:

  • 麻煩方法:用

    id(X)

    函數,對 X 進行某種操作,比較操作前後的

    id

    ,如果不一樣,則

    X

    不可變,如果一樣,則

    X

    可變。
  • 便捷方法:用

    hash(X)

    ,隻要不報錯,證明

    X

    可被哈希,即不可變,反過來不可被哈希,即可變。

【例子】

i = 1
print(id(i))  # 140732167000896
i = i + 2
print(id(i))  # 140732167000960

l = [1, 2]
print(id(l))  # 4300825160
l.append('Python')
print(id(l))  # 4300825160
           
  • 整數

    i

    在加 1 之後的

    id

    和之前不一樣,是以加完之後的這個

    i

    (雖然名字沒變),但不是加之前的那個

    i

    了,是以整數是不可變類型。
  • 清單

    l

    在附加

    'Python'

    之後的

    id

    和之前一樣,是以清單是可變類型。

【例子】

print(hash('Name'))  # -9215951442099718823

print(hash((1, 2, 'Python')))  # 823362308207799471

print(hash([1, 2, 'Python']))
# TypeError: unhashable type: 'list'

print(hash({1, 2, 3}))
# TypeError: unhashable type: 'set'
           
  • 數值、字元和元組 都能被哈希,是以它們是不可變類型。
  • 清單、集合、字典不能被哈希,是以它是可變類型。

建立字典的幾種方法

a = dict(one=1, two=2, three=3) #dict(**(kwargs)),keyword隻能是字元串,但不需要加引号
b = {'one': 1, 'two': 2, 'three': 3}
c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))
d = dict([('two', 2), ('one', 1), ('three', 3)]) #建立字典的方法,dict隻有一個參數,是以用元組/清單框起來
e = dict({'three': 3, 'one': 1, 'two': 2})
dict1 = dict((('F',70),('i',105),('s',115)))  #建立字典的方法,dict隻有一個參數,是以用元組框起來
dict2 = dict(小甲魚 = '讓程式設計改變世界',蒼井空 = '讓A片征服宅男')  #關鍵字參數,建立字典
#keyword不能是字元串
dict2['蒼井空'] = '老了'  #改變鍵的值
           

内置BIF

dict.fromkeys(seq[,value])  #在原字典的基礎上建立和傳回新的字典,以seq中的各元素作為字典的鍵,以value作為字典的值,值預設為None
#通路字典的方法
dict.keys()  #傳回一個iterable,可以用list()轉換為字典鍵的清單
dict.values() #傳回一個iterable,可以用list()轉換為字典值的清單
dict.items() #傳回一個iterable,鍵值對用tuple表示
dict.get(key,default = None) #有這個key就傳回這個值,沒有就傳回default的值,預設為None
dict.setdefault(key,default = None) #有這個key就傳回這個值,沒有就添加這個項(key, default)并傳回a
dict.clear()  #清空字典
dict.copy()  #淺拷貝,與直接指派不同,給對象貼标簽,若對象改變,标簽也改變
dict.pop(key[,default])  #給定鍵,彈出并傳回對應的值(value),若key不存在,則傳回default值
del(dict[key])  #删除字典給定鍵所對應的值
dict.popitem()  #彈出最後一個鍵值對(item)
dict.update(dict2)  #相當于清單的extend(),把字典參數dict的鍵值對更行到字典dict中
           
  • 字典中幾種拷貝方法的例子
from copy import deepcopy

dic1 = {'user': 'lsgogroup', 'num': [1, 2, 3]}

# 引用對象
dic2 = dic1  
# 淺拷貝父對象(一級目錄),子對象(二級目錄)不拷貝,還是引用
dic3 = dic1.copy()
# 深拷貝
dic4 = deepcopy(dic1)

print(id(dic1))  # 148635574728
print(id(dic2))  # 148635574728
print(id(dic3))  # 148635574344
print(id(dic4))  # 和上面不一樣

# 修改 data 資料
dic1['user'] = 'root'
dic1['num'].remove(1)

# 輸出結果
print(dic1)  # {'user': 'root', 'num': [2, 3]}
print(dic2)  # {'user': 'root', 'num': [2, 3]}
print(dic3)  # {'user': 'runoob', 'num': [2, 3]}
print(dic4)  # {'user': 'lsgogroup', 'num': [1, 2, 3]}
           
  • 成員資格操作符,運用在鍵中,在字典中查找的是鍵而不是值,而序列中查找的是元素的值而不是索引号

    key in dict

課後習題

2、字典中的value

有一個字典,儲存的是學生各個程式設計語言的成績,内容如下

data = {
        'python': {'上學期': '90', '下學期': '95'},
        'c++': ['95', '96', '97'],
        'java': [{'月考':'90', '期中考試': '94', '期末考試': '98'}]
        }
           

各門課程的考試成績存儲方式并不相同,有的用字典,有的用清單,但是分數都是字元串類型,請實作函數

transfer_score(score_dict)

,将分數修改成int類型

def transfer_score(data):
    # 暫時沒做出來,占個坑

           

集合

Python 中

set

dict

類似,也是一組

key

的集合,但不存儲

value

。由于

key

不能重複,是以,在

set

中,沒有重複的

key

注意,

key

為不可變類型,即可哈希的值。但是

set

是可變類型,與清單、字典相同。

【例子】

num = {}
print(type(num))  # <class 'dict'>
num = {1, 2, 3, 4}
print(type(num))  # <class 'set'>
           

集合的建立

# 直接建立空集合
basket = set()
# 增加元素
basket.add('1')
# 花括号擴起
basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
# 工廠函數轉化set()
a = set('abracadabra')
print(a)  
# {'r', 'b', 'd', 'c', 'a'}

b = set(("Google", "Lsgogroup", "Taobao", "Taobao"))
print(b)  
# {'Taobao', 'Lsgogroup', 'Google'}

c = set(["Google", "Lsgogroup", "Taobao", "Google"])
print(c)  
# {'Taobao', 'Lsgogroup', 'Google'}
           

集合的内置方法

set1.add(elmnt) # 用于給集合添加元素
set1.update(set) # 用于修改目前集合,可以添加新的元素或集合到目前集合中,如果添加的元素在集合中已存在,則該元素隻會出現一次,重複的會忽略。
x = {"apple", "banana", "cherry"}
y = {"google", "baidu", "apple"}
x.update(y)
print(x)
# {'cherry', 'banana', 'apple', 'google', 'baidu'}

y.update(["lsgo", "dreamtech"])
print(y)
# {'lsgo', 'baidu', 'dreamtech', 'apple', 'google'}

set1.remove(item) # 用于移除集合中的制定元素,若元素不存在,則會發生錯誤
set1.pop(item) # 用于随機移除一個元素
set1.intersection(set2) # 傳回set1 set2的交集
set1.intersection_update(set2) # 同樣的傳回交集,在原始的集合上取交集,沒有傳回值
set1 & set2 # 傳回兩個集合的交集
set1.union(set2) # 傳回兩個集合的并集
set1 | set2 # 傳回兩個集合的并集
set1.difference(set2) # 傳回集合的差集。
set1 - set2 # 傳回集合的差集。
set1.difference_update(set2) # 集合的差集,直接在原來的集合中移除元素,沒有傳回值。
set1.symmetric_difference(set2) # 傳回集合的異或。
set1 ^ set2 # 傳回集合的異或。
set1.symmetric_difference_update(set) # 移除目前集合中在另外一個指定集合相同的元素,并将另外一個指定集合中不同的元素插入到目前集合中。
set1.issubset(set) # 判斷集合是不是被其他集合包含,如果是則傳回 True,否則傳回 False。
set1 <= set2 # 判斷集合是不是被其他集合包含,如果是則傳回 True,否則傳回 False。
set1.issuperset(set) # 用于判斷集合是不是包含其他集合,如果是則傳回 True,否則傳回 False。
set1 >= set2 # 判斷集合是不是包含其他集合,如果是則傳回 True,否則傳回 False。
set1.isdisjoint(set2) # 用于判斷兩個集合是不是不相交,如果是傳回 True,否則傳回 False。
           

不可變集合

Python 提供了不能改變元素的集合的實作版本,即不能增加或删除元素,類型名叫

frozenset

。需要注意的是

frozenset

仍然可以進行集合操作,隻是不能用帶有

update

的方法。

  • frozenset([iterable])

    傳回一個當機的集合,當機後集合不能再添加或删除任何元素。

【例子】

a = frozenset(range(10))  # 生成一個新的不可變集合
print(a)  
# frozenset({0, 1, 2, 3, 4, 5, 6, 7, 8, 9})

b = frozenset('lsgogroup')
print(b)  
# frozenset({'g', 's', 'p', 'r', 'u', 'o', 'l'})
           

序列

在 Python 中,序列類型包括字元串、清單、元組、集合和字典,這些序列支援一些通用的操作,但比較特殊的是,集合和字典不支援索引、切片、相加和相乘操作。

Iterable對象的說明和相關内置函數

一類是集合資料類型,如

list

tuple

dict

set

str

等(這些都是序列);

一類是

generator

,包括生成器和帶

yield

的generator function。

這些可以直接作用于

for

循環的對象統稱為可疊代對象:

Iterable

可以被

next()

内置函數調用并不斷傳回下一個值的對象稱為疊代器:

Iterator

生成器都是

Iterator

對象,但

list

dict

str

雖然是

Iterable

,卻不是

Iterator

你可能會問,為什麼

list

dict

str

等資料類型不是

Iterator

這是因為Python的

Iterator

對象表示的是一個資料流,Iterator對象可以被

next()

函數調用并不斷傳回下一個資料,直到沒有資料時抛出

StopIteration

錯誤。可以把這個資料流看做是一個有序序列,但我們卻不能提前知道序列的長度,隻能不斷通過

next()

函數實作按需計算下一個資料,是以

Iterator

的計算是惰性的,隻有在需要傳回下一個資料時它才會計算。

list(iterable)  #把一個可疊代對象轉化為清單,沒有參數傳回空清單,有參數傳回疊代後的清單,字元串就是每個字元單獨組成的清單
tuple(iterable)  #把一個可疊代對象轉化為元組
len(iterable)  #傳回可疊代對象的長度
max()  #傳回序列與參數中的最大值,字母就傳回ASCII碼,字元串就傳回字元的ASCII碼
min()  #相反
sum(iterble[,start])  #傳回序列iterable與可選參數start的總和,隻有資料類型能實作sum操作
sorted(iterable, key = None(func), reverse = False)  #key用來進行元素的比較,隻有一個參數,具體的函數的參數就是取自于可疊代對象中,指定可疊代對象中的一個元素來進行排序,傳回重新排序的清單(這也是與sort的不同點,sort是直接改變清單)
reversed()  #同reverse,傳回可疊代對象,可轉化為清單
enumerate(sequence, [start=0])  #每一個值變成添加索引值後的元組,傳回一個疊代器對象,可轉化為清單,strat參數可以調整索引值的初始值
zip(a,b)  #講兩個序列裡的數打包成元組,傳回元組對象,可轉化為清單,a/b是序列(清單)
# 如果各個疊代器的元素個數不一緻,則傳回清單長度與最短的對象相同,利用 * 号操作符,可以将元組解壓為清單。
iter(iterable)  #傳回一個可疊代對象的疊代器
next(iter(iterable))  #傳回下一個疊代的值,這裡的iterable必須是可疊代對象
           

sorted()的用法

【例子】

x = [-8, 99, 3, 7, 83]
print(sorted(x))  # [-8, 3, 7, 83, 99]
print(sorted(x, reverse=True))  # [99, 83, 7, 3, -8]

t = ({"age": 20, "name": "a"}, {"age": 25, "name": "b"}, {"age": 10, "name": "c"})
x = sorted(t, key=lambda a: a["age"])
print(x)
# [{'age': 10, 'name': 'c'}, {'age': 20, 'name': 'a'}, {'age': 25, 'name': 'b'}]
           

zip()的用法

【例子】

a = [1, 2, 3]
b = [4, 5, 6]
c = [4, 5, 6, 7, 8]

zipped = zip(a, b)
print(zipped)  # <zip object at 0x000000C5D89EDD88>
print(list(zipped))  # [(1, 4), (2, 5), (3, 6)]
zipped = zip(a, c)
print(list(zipped))  # [(1, 4), (2, 5), (3, 6)]

a1, a2 = zip(*zip(a, b))
print(list(a1))  # [1, 2, 3]
print(list(a2))  # [4, 5, 6]
           

**python的星号作用,解包與打散,需要在此更新!