如何使glom与类似dict的对象一起工作

时间:2019-08-28 23:33:44

标签: python glom

格洛姆(https://glom.readthedocs.io/en/latest/)尤其适用于

  

基于路径的嵌套结构访问

但是您如何使其适用于除dicts之外的嵌套结构?

请考虑以下类(为简便起见,不实际使用collection.abc.Mapping

class MyMap: 
    def __init__(self, d):
        self.d = d
    def __getitem__(self, k):
        """just delegating"""
        v = self.d[k]
        if isinstance(v, (dict, MyMap)):
            return MyMap(v)
        else:
            return v

这有效:

m = MyMap({'a': {'b': {'c': 'd'}}})
assert m['a']['b']['c'] == 'd'

但这不是:

from glom import glom
assert glom(m, 'a.b.c') == 'd'

我得到了错误: PathAccessError: could not access 'a', part 0 of Path('a', 'b', 'c'), got error: AttributeError("'MyMap' object has no attribute 'a'")

更具体地,如何指定:

  • 什么是节点(即可以进一步模糊的对象)
  • 密钥迭代器(如何将路径拆分为密钥)
  • 项目获取器(如何从密钥中检索数据)

如果有帮助,这是我正在寻找的glom可以满足的功能:

dot_str_key_iterator = lambda p: p.split('.')
bracket_getter = lambda obj, k: obj[k]

def simple_glom(target, spec, 
                node_types=(dict,), 
                key_iterator=dot_str_key_iterator,
                item_getter=bracket_getter
               ):
    for k in key_iterator(spec):
        target = item_getter(target, k)
        if not isinstance(target, node_types):
            break
    return target

此功能并没有所有的花哨功能,但我可以这样做:

m = MyMap({'a': {'b': {'c': 'd'}}})
simple_glom(m, 'a.b.c', node_types=(MyMap,))

或者是使用所有参数设置的极端示例:

from types import FunctionType
from functools import partial

attr_glom = partial(simple_glom, 
                    node_types=(FunctionType, type), 
                    key_iterator=lambda p: p.split('/'), 
                    item_getter=getattr)
assert attr_glom(MyMap, '__getitem__/__doc__') == 'just delegating'

1 个答案:

答案 0 :(得分:0)

这些是很好的问题!我会尽力一次将它们分开:

如何指定对象可以被遮盖?

当您在这里说“ glom”时,我假设您的意思是“ access”。

Python具有非常丰富的数据模型,尽管通常在每种情况下都有 直观的含义,但猜测起来可能既昂贵又冒险。 glom的方法是provide explicit registration APIs

如何指定密钥迭代器?

如果要将路径(例如,'a.b.c'的{​​{1}})拆分为用于访问该路径的结构化键(和操作),我建议查看the Path type,特别是glom(target, 'a.b.c')Path.from_text()

如果您想查看一个对象并确定该对象内存在哪些路径,那会比较棘手。

在撰写本文时,path.items()仍主要用于访问和构建已知结构,并提供一些默认/分支功能。对于所有可能路径的完全无上下文迭代,我目前提供的最好是remapcookbook)。请注意,重新映射没有glom的插件/注册功能,但是它确实可以开箱即用地迭代常见Python数据类型中的可糊路径,如this example所示(相应的glom调用是在下面完成)。

如何指定如何从密钥中检索数据?

我认为上面提到的the registration APIs中确实解决了这一问题。 glom()关键字参数指的是内置操作,必须为所有类型都指定。

如果您“检索”的定义与内置get注册有冲突,可以覆盖它,可以指定可以针对其注册的新操作使用register_op(例如,如何添加assign操作)。

同样,很好的问题,您实际上是在这里利用Python的功能。希望这会有所帮助!