Python筆記004-元組的拆包和命名元組
以下是我學習《流暢的Python》後的個人筆記,現在拿出來和大家共享,希望能幫到各位Python學習者。
首次發表於: 微信公衆號:科技老丁哥,ID: TechDing,敬請關注。
本篇主要知識點:
-
元組的拆包就是將元組內部的每個元素按照位置一一對應的賦值給不同變量,可以應用到變量賦值,函數參數賦值,獲取元組中特定位置的元素值等場合。
-
namedtuple: 用於存儲對象序列,不能改變元素值,可以像dict一樣通過名字進行訪問,可以通過_asdict()轉換爲dict,其作用相當於只有屬性沒有方法的類。
1. 元組的拆包
Python中的元組tuple和列表list類似,不同之處在於元組的元素不能修改,所以被經常稱爲不可變列表,在形式上,元組用小括號()表示,而列表用中括號[]表示。
元組的拆包就是將元組內部的每個元素按照位置一一對應的賦值給不同變量,比如:
tupleA=(10,20.5)
first,second=tupleA # 對二元素元組拆包
print(first) # 10
print(second) # 20.5
a,b,c,d=('A',20.15,2019,'10:15:14') # 多元素元組的拆包
print(a) # A
print(b) # 20.15
print(c) # 2019
print(d) # 10:15:14
如果拆包應用於上面的簡單賦值,那倒是沒什麼新奇之處。拆包其實被經常用於給函數的參數賦值,比如:
def func1(a,b):
print('a: ',a,'b: ',b)
tupleA=(10,20.5)
func1(*tupleA) # 拆包後作爲函數的參數,a: 10 b: 20.5
另外一種拆包的應用場景是,某些函數返回一個tuple,而我們需要對其進行拆包,比如:
def func2(x):
return (x,x*2,x*x)
data1,data2,data3=func2(3)
print(data1) # 3
print(data2) # 6
print(data3) # 9
在拆包時,有的元素不是我們所需要的,那就用佔位符來代替,即用_代表一個佔位符,而*代表多個佔位符
data1,_,data3=func2(3) # 用_代表一個變量
print(data1) # 3
data1,*rest=func2(3)
print(data1) # 3
print(rest) # [6,9]
嵌套元組,顧名思義是元組中包含有元組,對其進行拆包和普通元組的拆包類似。
areas=[('hubei','wuhan',1200,(150,260)),
('hunan','changsha',3600,(100,200)),
('shandong','jinan',800,(260,180))]
for province,city,data1,(data2,data3) in areas:
print('P:{}, C:{}, data2:{},data3:{}'.format(province,city,data2,data3))
2. 命名元組
命名元組(namedtuple)類似於tuple,都可以用於存儲對象序列,但是它比tuple更加強大,除了延續tuple不能改變元素值這一特性之外,還有其本身的特點,比如可以像dict一樣通過名字訪問元素值,還可以通過_asdict()轉換爲dict類型。
命名元組可以構建一個帶有字段名的元組和一個有名字的類,其消耗的內存和元組是一樣的。
在面向對象的思想下,如果我們需要構建一個簡單的類,只是用於存儲幾個簡單的屬性,而沒有具體的方法,我們可以寫成:
class PersonCls:# 定義一個類,只有屬性,沒有具體的方法,用於存儲某些屬性值
def __init__(self,name,age,score):
self.name=name
self.age=age
self.score=score
def __repr__(self):
return 'PersonCls(name={},age={},score={})'.format(self.name,self.age,self.score)
PC1=PersonCls('Jack',20,85)
PC2=PersonCls('Rose',18,92)
print(PC1) # PersonCls(name=Jack,age=20,score=85)
print(PC2) # PersonCls(name=Rose,age=18,score=92)
print(PC1.age) # 20
print(PC2.score) # 92
這樣的寫法是可行的,但不是Python風格,對這種情況,完全可以交給namedtuple來做,比如,在python裏面的寫法爲:
from collections import namedtuple
Person=namedtuple('Person',['name', 'age', 'score']) # 構造一個namedtuple類
P1=Person('Jack',20,85) # 構建具體的實例,其賦值順序要一一對應
P2=Person(age=18,name='Rose',score=92) # 如果指定變量名,順序不用一一對應
print(P1) # Person(name='Jack', age=20, score=85)
print(P2) # Person(name='Rose', age=18, score=92)
print(P1.age) # 可以像dict一樣通過屬性名進行訪問
print(P2.score) # 92
上面的Person=namedtuple('Person',['name', 'age', 'score'])
就相當於構建一個只有屬性沒有方法的Person類,其屬性爲:‘name’, ‘age’, ‘score’,代碼更加簡單,且更有Python味兒。在內存上來說,會比定義一個類要小一些,因爲此時不需要用__dict__
來存放實例的屬性。
命名元組除了從tuple繼承來的屬性之外,還有其專有屬性,最常用的是_fields, _make(), _asdict()
。如下:
# namedtuple專有屬性:
from collections import namedtuple
Person=namedtuple('Person',['name', 'age', 'score'])
print(Person._fields) # ('name', 'age', 'score')
# _fields屬性是一個包含這個類所有屬性名稱的tuple
person1=('zhangsan',25,59)
p1=Person._make(person1) # _make()接受一個可迭代對象生成一個實例
print(p1) # Person(name='zhangsan', age=25, score=59)
print(p1._asdict()) # OrderedDict([('name', 'zhangsan'), ('age', 25), ('score', 59)])
# _asdict()將實例的屬性和值以OrderedDict的方式展示出來。
首次發表於: 微信公衆號:科技老丁哥,ID: TechDing,敬請關注。
本文所有代碼都已經上傳到我的github,歡迎下載
參考資料:
- 《流暢的Python》,Luciano Ramalho (作者) 安道 , 吳珂 (譯者)。