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

How to make glom work with dict-like objects

Glom (https://glom.readthedocs.io/en/latest/) 除其他外,还用于

path-based access for nested structures

但是如何让它适用于字典以外的嵌套结构?

考虑以下 class(为简单起见,故意不是实际的 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'

这些都是很好的问题!我会尽力一次把它们分解出来:

如何指定对象可以 glommed?

当你在这里说 "glom" 时,我假设你的意思是 "access"。

Python 具有非常丰富的数据模型,虽然 通常 在任何情况下 "access" 都有直观的含义,但它可能代价高昂且存在风险猜测。 glom 对此的处理方法是 provide explicit registration APIs.

如何指定一个键迭代器?

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

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

在撰写本文时,glom 仍主要用于访问和构建已知结构,并为 defaults/branching 提供一些功能。对于所有可能路径的完整上下文无关迭代,我目前必须提供的最好的是 remap (cookbook). Note that remap doesn't have glom's plugin/registration power, but it does work out-of-the-box for iterating glommable paths in common Python datatypes, as this example 显示(相应的 glom() 调用在下面完成)。

如何指定如何从键中检索数据?

我认为这实际上在我上面提到的 the registration APIs 中得到了解决。 get 关键字参数指的是一个内置操作,必须为所有类型指定。

如果您对 "retrieve" 的定义与内置 get 注册冲突,您可以覆盖它, 您可以指定一个添加了可以使用 register_op, (e.g., how the assign 操作注册的新操作。

再一次,很好的问题,你真的在​​这里利用了 Python 的力量。希望这对您有所帮助!