天天看點

在Python中以"foo.bar.baz"的方式通路嵌套dict中的内容

我們首先舉一個多級嵌套的dict的例子,後面也會用這個例子來結合代碼說明:

obj = {
  "foo": {
    "bar": {
      "baz": 5
    }
  }
}           

javascript中,可以通過lodash的get方法來擷取上面的object中形如"foo.bar.baz"的路徑所對應的值,比如

_.get(obj, "foo.bar.baz")

。那麼在Python中需要如何操作呢?一個簡單的方法是使用functools中的reduce方法來完成:

import functools

path = "foo.bar.baz"
value = functools.reduce(dict.get, path.split('.'), obj)  # value == 5           

上面代碼采用的是一種非常聰明的方法,巧妙的的通過reduce函數的使用,把一般來說需要通過循環和遞歸才能解決的問題通過一行代碼就解決了

如果在Python 3.8版本之後,我們可以通過list comprehension的walrus operator(就是:=)來做另外一個比較簡潔的實作:

path = "foo.bar.baz"
result = obj
__ = [result := dict.get(result, i) for i in path.split('.')]  # result == 5           

如果我們需要讓上述的函數支援對于不存在的key的容錯,那麼可以用一個lambda函數來代替dict.get,比如

lambda o, k: dict.get(o or {}, key,)

,這樣就可以比較簡單在Python直接完成類似于lodash.get的效果了。當然,進一步的增加類型判斷還可以讓這個函數更加的容錯。