[TOC]python
哈嘍,你們好!距離上一篇文章近1個半月了,不是我拖呀~,恰好這個月遇到了工做調整,再加上要照顧10個月的孩子,實屬不易,因此就這麼長時間沒來更新了。這不,我天天碼一點點,'滴水成河',努力完成了這篇文章。express
說明: 等號(=)右邊有多個數值僅經過逗號分割,就會封裝到一個元組,稱爲封裝packing。數據結構
# 示例:
x = 1,
y = 1,2
print(type(x), x)
print(type(y), y)
# 輸出結果以下:
<class 'tuple'> (1,)
<class 'tuple'> (1, 2)複製代碼
備註: 若是右邊只有一個數值且沒有用逗號,實際上是一個整數類型,請留意。另外等號右邊必定先運行,再賦值給左邊。app
說明: 等號(=)右邊容器類型的元素與左邊經過逗號分割的變量要一 一對應,稱爲解構unpacking。函數
x,y = (1,2) # [1,2] {1,2} {'a':1,'b':2}
print(x)
print(y)
# 輸出結果以下:
1
2複製代碼
備註:右邊的容器能夠是元組、列表、字典、集合等,必須是可迭代對象。spa
錯誤示範:rest
x,y = (1,2,3)
print(x)
print(y)
# 輸出結果以下:
ValueError: too many values to unpack (expected 2)複製代碼
說明:左、右兩邊個數必定要一致,否則會拋出'ValueError'錯誤。code
剩餘變量解構cdn
說明:python3引入了剩餘變量解構(rest),'儘量'收集剩下的數據組成一個列表。對象
x, *rest = [1,2,3,4,5,6]
print(type(x), x)
print(type(rest), rest) # 剩餘沒有賦值的就是rest的了
# 輸出結果以下:
<class 'int'> 1
<class 'list'> [2, 3, 4, 5, 6]複製代碼
*rest, y = [1,2,3,4,5,6]
print(type(rest), rest)
print(type(y), y)
# 輸出結果以下:
<class 'list'> [1, 2, 3, 4, 5]
<class 'int'> 6複製代碼
錯誤示例:
不能單獨使用
說明:等號左邊只有一個標識符,沒法解構。
*rest = [1,2,3,4,5,6]
print(rest)
# 輸出結果以下:
#語法錯誤
SyntaxError: starred assignment target must be in a list or tuple複製代碼
不能屢次同時使用
x, *rest1, *rest2, y = [1,2,3,4,5,6]
print(rest1)
print(rest2)
# 輸出結果以下:
#語法錯誤,其中一個rest就把剩餘元素拿走了,另一個rest怎麼拿?
SyntaxError: two starred expressions in assignment複製代碼
另一種丟棄變量下劃線:'_'
說明: '_'是合法的標識符,大多場景表示不關心該值。
x, *_, y = [1,2,3,4,5,6]
print(x)
print(_)
print(y)
# 輸出結果以下:
1
[2, 3, 4, 5]
6複製代碼
_, *rest, _ = [1,2,3,4,5,6]
print(_) # '_'是上一次輸出值
print(rest)
# 輸出結果以下:
6
[2, 3, 4, 5]複製代碼
說明:集合是'可變的、無序的、不重複'的元素集合。
成爲集合元素是有條件的:'元素必須可hash、可迭代'
可哈希對象以下(不可變):
能夠經過內置hash函數判斷是否可hash:
s1 = [1,2,3]
print(hash(s1))
# 輸出結果以下:
TypeError: unhashable type: 'list' # 列表是不可hash的複製代碼
說明:
s = {} # 注意這個是空字典,不是空集合
s1 = set() # 空集合
s2 = set([1,2,3]) # 注意列表裏面元素迭代出來的是整數,可hash
s3 = set("abcd")
print(s1)
print(s2)
print(s3)
# 輸出結果以下:
set()
{1, 2, 3}
{'c', 'd', 'a', 'b'}複製代碼
錯誤示例:
s = set([[1]]) # 列表套列表,迭代出來是列表,不可hash
print(s)
# 輸出結果以下:
TypeError: unhashable type: 'list'複製代碼
s.add(element)
說明:增長一個元素到集合,若是元素已經存在,則不操做。
s1 = set([1,2,3])
s1.add(4)
print(s1)
# 輸出結果以下:
{1, 2, 3, 4}複製代碼
s.update(*element))
說明:合併一個或多個元素到集合中,元素必須可迭代(把迭代的元素併到集合),和後面講的並集同樣。
s1 = set([1,2,3])
s1.update((4,5,6),[7,8,9])
print(s1)
# 輸出結果以下:
{1, 2, 3, 4, 5, 6, 7, 8, 9}複製代碼
remove(element)
說明:從集合中移除一個元素,若是元素不存在拋出'KeyError'錯誤。
s1 = {1,2,3,4,5,6}
s1.remove(6)
print(s1)
# 輸出結果以下:
{1, 2, 3, 4, 5}複製代碼
discard(element)
說明:也是從集合中移除一個元素,若是元素不存在不會報異常,啥都不作。
s1 = {1,2,3,4,5,6}
s1.discard(6)
print(s1)
# 輸出結果以下:
{1, 2, 3, 4, 5}複製代碼
pop()
說明:由於集合是無序的,因此是刪除'任意'一個元素,若是是空集則拋出'KeyError'錯誤。
s1 = {1,2,3,4,5,6}
print(s1.pop()) # 隨機的(由於無序)
print(s1)
# 輸出結果以下:
1
{2, 3, 4, 5, 6}複製代碼
clear()
說明:刪除全部元素,都不推薦使用的啦。
s1 = {1,2,3,4,5,6}
s1.clear()
print(s1)
# 輸出結果以下:
set()複製代碼
說明:集合是個容器,是能夠遍歷的,可是效率都是O(n)。
s1 = {1,2,3}
for s in s1:
print(s)
# 輸出結果以下:
1
2
3複製代碼
說到這裏,你以爲集合set和列表list哪一個遍歷效率更高呢?
答案是set,由於set的元素是hash值做爲key(下面講的字典也是hash值),查詢時間複雜度爲O(1),而list是線性數據結構,時間複雜度是O(n)。
你們能夠按照以下進行驗證下,隨着數據規模愈來愈大,很明顯就能夠看出哪一個效率高。
並集
說明: 將多個集合的全部元素合併在一塊兒組成新的集合。
s1 = {1,2,3}
s2 = {3,4,5}
print(s1.union(s2))
# 輸出結果以下:
{1, 2, 3, 4, 5}複製代碼
備註:還可使用運算符 '|'、'update(element)'、'|='。
交集
說明: 取多個集合的共同(相交)元素
s1 = {1,2,3}
s2 = {3,4,5}
print(s1.intersection(s2))
# 輸出結果以下:
{3}複製代碼
備註:還可使用'&'、's.intersection_update(element)'、'&='。
差集
說明:屬於一個集合但不屬於另外一個集合的元素組成的集合。
s1 = {1,2,3}
s2 = {3,4,5}
print(s1.difference(s2))
# 輸出結果以下:
{1, 2}複製代碼
備註:還可使用'-'、's.difference_update(element)'、'-='.
對稱差集
說明:多個集合中,不屬於交集元素組成的集合。
s1 = {1,2,3}
s2 = {3,4,5}
print(s1.symmetric_difference(s2))
# 輸出結果以下:
{1, 2, 4, 5}複製代碼
備註:還可使用'^'、's1.symmetric_difference_update(s2)'、'^='.
說明:字典是由任意個item(元素)組成的集合,item是由key:value對組成的二元組。
# 空字典
d1 = {}
d2 = dict()
# 示例:
d3 = dict(a=1,b=2,c=3)
d4 = dict(d3)
d5 = dict([('a',1),('b',2),('c',3)]) # 元素必須是可迭代的
d6 = {'a':1,'b':2,'c':3}
# 輸出結果都是:
{'a': 1, 'b': 2, 'c': 3}複製代碼
增長&修改元素
1)經過'd[key] = value'方式:
備註:若是key不存在,則新增,key存在則直接覆蓋(修改元素)。
# 增長 & 修改
d = {'a':1,'b':2,'c':3}
d['d'] = 4 # 增長
d['a'] = 11 # 修改
print(d)
# 輸出結果以下:
{'a': 11, 'b': 2, 'c': 3, 'd': 4}複製代碼
2)經過d.update([E, ]**F) -> None
# 增長 & 修改
d = {'a':1,'b':2,'c':3}
d.update(d=4)
print(d)
# 輸出結果以下:
{'a': 1, 'b': 2, 'c': 3, 'd': 4}複製代碼
刪除元素
1)d.pop()
d = {'a':1,'b':2,'c':3}
print(d.pop('c',None))
print(d)
# 輸出結果以下:
3
{'a': 1, 'b': 2}複製代碼
2)d.popitem()
d = {'a':1,'b':2,'c':3}
print(d.popitem())
print(d)
# 輸出結果以下:
('c', 3)
{'a': 1, 'b': 2}複製代碼
3)d.clear()
d = {'a':1,'b':2,'c':3}
d.clear()
print(d)複製代碼
查找元素
正常訪問元素:
d = {'a':1,'b':2,'c':3}
print(d['a'])
print(d.get('b'))
# 輸出結果以下:
1
2複製代碼
key不存在的處理方式:
d = {'a':1,'b':2,'c':3}
print(d.get('d',None)) # 若是key不存在,缺省返回None
print(d.setdefault('d',100)) # 若是key不存在,則新增key:value對
print(d)
# 輸出結果以下:
None
100
{'a': 1, 'b': 2, 'c': 3, 'd': 100}複製代碼
遍歷鍵:key
d = {'a':1,'b':2,'c':3}
# 方法1:
for k in d: # 缺省是遍歷key
print(k)
# 方法2:
for k in d.keys():
print(k)
# 方法3:
for k, _ in d.items():
print(k)
# 輸出結果以下:
a
b
c複製代碼
遍歷值:value
d = {'a':1,'b':2,'c':3}
# 方法1:
for v in d.values():
print(v)
# 方法2:
for k in d:
# print(d[k]) # 也能夠用
print(d.get(k))
# 方法3:
for _, v in d.items():
print(v)
# 輸出結果以下:
1
2
3複製代碼
遍歷item:key-value
d = {'a':1,'b':2,'c':3}
for item in d.items():
print(item)
# 輸出結果以下:
('a', 1)
('b', 2)
('c', 3)複製代碼
其餘問題
這種狀況在遍歷的時候,不可以刪除元素,不能改變字典的size。
d = {'a':1,'b':2,'c':3}
for k in d:
print(d.pop(k))
# 輸出結果以下:
RuntimeError: dictionary changed size during iteration複製代碼
優雅的刪除方式:
d = {'a':1,'b':2,'c':3}
key_list = []
for k in d:
key_list.append(k)
for k in key_list:
print('已刪除key:', d.pop(k))複製代碼
然並卵,想要清除,直接用clear()啦。
語法
優勢
示例需求:請從給定區間中提取可以被2整除的元素。
大衆廣泛的寫法:
list = []
for i in range(10):
if i % 2 == 0:
list.append(i)
print(list)
# 輸出結果以下:
[0, 2, 4, 6, 8]複製代碼
再來感覺一下簡單而優雅的寫法:
print([i for i in range(10) if i % 2 == 0])
# 輸出結果以下:
[0, 2, 4, 6, 8]複製代碼
以上就是列表解析式,也叫列表推倒式。
語法
特色:
看下生成器對象是長什麼樣的(不要認爲是元組解析式,哈哈):
x = (i for i in range(10) if i % 2 == 0)
print(type(x))
print(x)
# 輸出結果以下:
<class 'generator'> # 生成器
<generator object <genexpr> at 0x000001A143ACBA98> # 生成器對象複製代碼
那生成器對象是如何計算獲得結果:
import time
x = (i for i in range(10) if i % 2 == 0)
for i in range(6): # 僅一次循環取值
time.sleep(0.5)
print(next(x))
time.sleep(1)
print(next(x)) # for循環已經計算完全部結果了,不能取值,故拋出異常
# 輸出結果以下:
0
2
4
6
8
StopIteration # 已經超出可迭代範圍,拋出異常複製代碼
備註:生成器表達式只能迭代一次。
集合解析式和列表解析式語法相似,不作過多解析。
語法:
示例:
print({i for i in range(10) if i % 2 == 0})
# 輸出結果以下:
{0, 2, 4, 6, 8}複製代碼
字典解析式和集合解析式語法相似,不作過多解析。
語法:
示例:
print({i:(i+1) for i in range(10) if i % 2 == 0})
# 輸出結果以下:
{0: 1, 2: 3, 4: 5, 6: 7, 8: 9}複製代碼
整體來講,解析式寫起來若是讓人簡單易懂、又高效,是很是推薦你們使用的。
但有的場景寫起來很複雜,那仍是得用for...in循環拆分來寫。
若是喜歡的個人文章,歡迎關注個人公衆號:點滴技術,掃碼關注,不按期分享