glom
是一种用Python处理数据的新方法,具有以下特点:
- 嵌套结构并基于路径访问
- 使用轻量级的Pythonic规范进行声明性数据转换
- 可读、有意义的错误信息
- 内置数据探测和调试功能
- …
在上一篇博文当中,简要记录一下glom
的使用,以及一些它的特性!接下来,将记录一下glom
更多方法的使用:
glom.glom(target, spec, **kwargs)
从给定的target,根据spec声明规范构造一个值
反问嵌套数据,我们可以这样:
from glom import glom
target = {"a": {"b": "c"}}
print(glom(target, "a.b")) # c
这里的规范一个表示路径的字符串。下面我们来构建或重构更加复杂的嵌套数据:
from glom import glom
target = {"a": 1, "b": {"c": 1, "d": 2}, "c": [0, 1, 2]}
spec = {"a": "a", "b": "b.c", "c": ("c", [lambda x: x * 2])}
print(glom(target, spec))
######## 打印结果如下 ########
{'a': 1, 'b': 1, 'c': [0, 2, 4]}
glom
还支持一个default参数用于设置默认值。如果设置了此值,那么glom
操作失败之后将会自动返回默认值,类似dict.get()
,如下:
spec = "a.xx"
print(glom(target, spec, default=1234)) # 1234
在target数据中可以看到,并没有哪个路径为“a.xx”,所以glom
返回默认值为1234。
另外,我们还可以指定skip_exc
参数来控制哪些错误应该被忽略,如下:
print(glom({}, lambda x: 100 / len(x), default=0, skip_exc=ZeroDivisionError)) # 0
glom
支持的参数说明如下:
- target:
glom
将在其上运行的对象 - spec:以
dict
、list
、tuple
、string
,或其他glom结构,以及这些结构的任何组合 - default:出现异常时,将返回该值
- skip_exc:一个可选异常或可忽略的异常元组
- scope:可以通过
glom-spec
中的S访问的其他数据(不是特别理解!!)
glom.Path(*path_parts)
当a.b.c
此类常规样式语法不起作用或不可取时,Path对象指定显示路径。使用它来包装整数、日期时间和其他有效键,以及带有不应展开的点的字符串:
from glom import glom, Path
target = {"a": {"b": 1, "c.d": 2, 2: 3}}
print(glom(target, Path("a", "c.d"))) # 2
print(glom(target, Path("a", 2))) # 3
在上面的栗子,如果使用a.c.d
和a.2
来进行匹配获取的话,将会发生错误!
Path对象可以将其他Path对象或者T对象连接到一起:
>>> from glom import Path, T
>>> Path(Path("a", 1), Path("b", 2))
Path("a", 1, "b", 2)
>>> Path(T["a"], T["b"])
T["a"]["b"]
Path对象还支持索引和切片,每次反问都是返回一个新的Path对象:
>>> from glom import Path
>>> p = Path("a", "b", "c", "d")
>>> p[0]
Path("a")
>>> p[0:2]
Path("a", "b")
glom.Literal(value)
Literal
对象在少数情况下指定文字值,而不应将部分规范解释为glommable subspec。无论在规范中遇到Literal对象,它都会被包含中的值替换:
from glom import glom, Literal
target = {"a": {"b": "c"}}
spec = {"name": "a.b", "age": Literal(18)}
print(glom(target, spec))
######## 打印结果如下 ########
{'name': 'c', 'age': 18}
glom.Spec(spec, scope=None)
具有类似于Literal
的用法,也具有glom
函数的操作,如下:
from glom import glom, Spec
target = {"a": {"b": "c"}, "d": 1}
spec = {"a": "a.b", "s": Spec("d")}
print(glom(target, spec)) # {'a': 'c', 's': 1}
Spec
还有自带的glom()
方法,用法如下:
from glom import Spec
target = {"a": {"b": "c"}, "d": 1}
s = Spec("a.b")
print(s.glom(target)) # c
glom.Coalesce(*subspecs, **kwargs)
Coalesce
是一个glom
结构,允许你为你的子目录指定回退行为。但是,如果有一组数据,同时满足Coalesce
中的所有匹配,那么它将会依次匹配,直到满足匹配为止!
from glom import glom, Coalesce
target = {"a": {"b": "c"}, "d": 1}
spec = {"result": Coalesce("a.c", "a.b")}
print(glom(target, spec)) # {"result": "c"}
同样,Coalesce
也可以指定default
参数来设置默认值,如下:
from glom import glom, Coalesce
target = {"a": {"b": "c"}, "d": 1}
spec = {"result": Coalesce("a.c", "a.d", default=0)}
print(glom(target, spec)) # {"result": 0}
Coalesce
支持的参数说明如下:
- subspecs:一个或多个glommable规范
- default:默认值,如果subspecs都未曾匹配将返回默认值
- default_factory:一个执行的函数,作为默认值返回
- skip:表示要忽略的值、值元组或者匿名函数
- skip_exc:一个可选异常或可忽略的异常元组
default_factory
参数用法如下:
from glom import glom, Coalesce
def default_factory():
return 0
target = {"a": {"b": "c"}, "d": 1}
spec = {"result": Coalesce("a.c", "a.d", default_factory=default_factory)}
print(glom(target, spec)) # {"result": 0}
skip
参数用法如下:
from glom import glom, Coalesce
target = {"a": {"b": "c"}, "d": 1}
spec = {"result": Coalesce("a.b", "d", skip="c")}
print(glom(target, spec)) # {"result": 1}
target = {"a": {"b": "c"}, "d": 1}
spec = {"result": Coalesce("a.b", "d", skip=("c", ))}
print(glom(target, spec)) # {"result": 1}
target = {"a": {"b": "c"}, "d": 1}
spec = {"result": Coalesce("a.b", skip=lambda x: x, default=0)}
print(glom(target, spec)) # {"result": 0}
从上面三个栗子中可以看到,第一个匹配条件都是符合的,但是因为有skip
参数,而且值正好与skip
中所设置的符合,所以将会往下匹配!直到不符合情况为止!skip_exc
用法与glom()
中的skip_exc
参数用法一致!
glom.OMIT
取消赋值操作
使用如下:
from glom import glom, OMIT
target = {"a": "b"}
spec = {"result": lambda x: x["a"] if x["a"] == "a" else OMIT}
print(glom(target, spec)) # {}
glom.assign(obj, path, val)
修改嵌套数据的结构
使用如下:
from glom import glom, assign
target = {"a": [{"name": "laozhang"}]}
_ = assign(target, "a.0.name", "laowang")
print(target) # {"a": [{"name": "laowang"}]}
a.0.name
其中0表示列表中的第一个元素
glom.Assign(path, val)
当不需要复制时,Assign可用于对大型数据结构进行临时修改:
from glom import glom, Assign
target = {"a": {}}
spec = Assign("a.b", 1)
_ = glom(target, spec)
print(target) # {"a": {"b": 1}}
要分配的值也可以是一个Spec
,这对于复制数据结构中的值非常有用:
from glom import glom, Assin, Spec
target = {"a": {"b": "c"}}
spec = Assign("a.c", Spec("a.b"))
_ = glom(target, spec)
print(target) # {"a": {"b": "c", "c": "c"}}