Python glom包初探
大家好, 我是四毛。
這一篇是關于glom的一個介紹與初步使用,后期會將里面的各種API再給大家介紹下,。
因為是邊看,邊練習,然后翻譯,所以個人理解可能有偏差,有錯誤的地方,請大家指正。
視頻地址:https://www.youtube.com/watch?v=bTAFl8P2DkE&t=18m07s
1. 官方文檔地址
文檔地址
2. 安裝方法
pip?install?glom
3. 正式開始
glom,官方的說法是用PYTHONIC的方式來處理內嵌的數據。對于現實世界中的數據處理更加給力,現實世界中的數據,我的理解就是AJAX越來越流行了,處理這類數據會越來越頻繁。有如下特點:
對于嵌套數據結構的基于路徑式的訪問
可讀,有意義的錯誤消息
聲明性數據轉換,使用輕量級,Pythonic規范
內置數據探索和調試功能
3.1 原始處理嵌套數據
下面的腳本包導入
from?glom?import?glom
下面的data就是個簡單的嵌套數據,一般都可以用下面幾種方法進行處理
data?=?{'a':?{'b':?{'c':?'d'}}} data['a']['b']['c'] data.get('a').get('b').get('c') data.get('a',?{}).get('b',{}).get('c')
但是當我們的數據改變成下面的這樣時:
data2?=?{'a':?{'b':?None}} data2['a']['b']['c'] Traceback?(most?recent?call?last): ... TypeError:?'NoneType'?object?has?no?attribute?'__getitem__'
會報錯,而且由于是嵌套數據,從錯誤信息里我們只知道有個None值,但是到底誰是呢,是a,是b呢,反正肯定不是我們的朋友小哪吒。
3.2 glom出場
那么glom怎么處理上面的數據呢? 如其所言,路徑式:
data?=?{'a':?{'b':?{'c':?'d'}}} print?glom(data,?'a.b.c')??#?d
看起來還是很優雅, 很Pythonic。
data2?=?{'a':?{'b':?None}} glom(data2,?'a.b.c')
錯誤信息如下:
glom.core.PathAccessError:?could?not?access?'c',?part?2?of?Path('a',?'b',?'c'),?got?error:?AttributeError("'NoneType'?object?has?no?attribute?'c'",)
很明顯,這個錯誤就很直觀。 難道僅僅只有這個?當然不是
3.2.1??Going Beyond Access
上面的是原標題,我的理解是不僅僅獲取數據,還有別的呢。 首先,介紹兩個基本的術語
target?目標數據,可以是字典,列表,或其他任意的對象 spec??我們想要的輸出格式?【specifications】,?定義你自己所需要的格式
現在讓我們跟隨宇航員的腳步,探索太陽系吧。
獲取某個行星的名字:
target?=?{'galaxy':?{'system':?{'planet':?'jupiter'}}} #?這個格式就是需要個字段值,所以輸出的就是個字段值 spec?=?'galaxy.system.planet' glom(target,?spec) #?'jupyter'
現在,宇航員們想把行星的名字放進一個列表中,數據是這樣:
target?=?{'system':?{'planets':?[{'name':?'earth'},?{'name':?'jupiter'}]}}
通常,處理這樣的話,都要寫個循環,或者搞個列表解析式,那么glom怎么處理呢?
glom(target,?('system.planets',?['name'])) print?glom(target,?spec) #?['earth',?'jupiter']
是不是很簡單。那么現在新需求又來了,宇航員想得到下面這個數據里面的行星的衛星的數:
target?=?{'system':?{'planets':?[{'name':?'earth',?'moons':?1}, ??????????????????????????????????{'name':?'jupiter',?'moons':?69}]}}
glom解決方法:
#?自定義的格式 spec?=?{'names':?('system.planets',?['name']), ????????'moons':?('system.planets',?['moons'])} print?glom(target,?spec) #?{'moons':?[1,?69],?'names':?['earth',?'jupiter']}
3.2.2? Changing Requirements
Coalesce 是glom定義的一種結構,允許我們對于spec中的子spec進行進一步的處理,你只要在子spec中將可能存在的值定義好就行了,聽起來有點繞,現在來梳理一下。
首先,子spec是什么?
spec?=?{'names':?('system.planets',?['name']), ?????????'moons':?('system.planets',?['moons'])} #?以這個為例,這里面的system.planets就是個子spec
然后,使用其解析數據:
target?=?{'system':?{ ????'planets':?[{'name':?'earth',?'moons':?1},?{'name':?'jupiter',?'moons':?69}], } } spec?=?{'names':?(Coalesce('system.planets',?'system.dwarf_planets'),?['name']), ?????????'moons':?(Coalesce('system.planets',?'system.dwarf_planets'),?['moons'])} print?glom(target,?spec) #?{'moons':?[1,?69],?'names':?['earth',?'jupiter']}
接著當我們的數據變成了這個以后
target?=?{'system':?{'dwarf_planets':?[{'name':?'pluto',?'moons':?5}, ????????????????????????????????????????{'name':?'ceres',?'moons':?0}]}} spec?=?{'names':?(Coalesce('system.planets',?'system.dwarf_planets'),?['name']), ?????????'moons':?(Coalesce('system.planets',?'system.dwarf_planets'),?['moons'])} print?glom(target,?spec) #?{'moons':?[5,?0],?'names':?['pluto',?'ceres']}
可以看到,依然可以使用相同的spec來解析不同的目標數據。 有意思的是,你可以在target里面同時寫入plantes和dwarf_plants數據試試看,會返回什么數據。 【這里應該是個惰性的匹配,只要匹配到一個,后面的就不再去匹配了】
3.2.3? True Python Native
真正的原生python 在glom里面,你可以傳值給python里面的任意的函數 舉例:
求和
target?=?{'system':?{'planets':?[{'name':?'earth',?'moons':?1}, ??????????????????????????????????{'name':?'jupiter',?'moons':?69}]}} print?glom(target,?{'moon_count':?('system.planets',?['moons'],?sum)}) #?{'moon_count':?70}
原教程這里還有個案例,但是我還沒有理解好,就不寫出來了,大家可以點擊鏈接自己看一下。
4. 結論
下一節,為大家帶來其中一些重要的函數。 最后,在用的過程中,一直有個疑問,數據如下:
target?=?{ ????'data':?{ ????????'name':?'just_test', ????????'likes':?[{'ball':?'basketball'}, ??????????????????{'ball':?'football'}, ??????????????????{'water':?'swim'}] ????} }
現在,我想返回的數據格式為:
{'name':?'just_for_test',?'likes':?['basketball',?'football',?'water']}
一開始我以為可以這么用:
spec?=?{ ????'name':?('data.name'), ????'likes':?('data.likes',?['ball',?'water']?), }
但是不行,這樣會報錯。后來用了另外的方法:
spec?=?{ ????'name':?('data.name'), ????'likes':?('data.likes',?[lambda?x:?x.values()[0]?if?'ball'?or?'water'?in?x.keys()?else?'']?), } print?glom(target,?spec) #?{'name':?'just_test',?'likes':?['basketball',?'football',?'swim']}
這樣感覺很不爽啊,還望會的同學不吝賜教啊。
python
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。