格洛姆(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'
答案 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()
仍主要用于访问和构建已知结构,并提供一些默认/分支功能。对于所有可能路径的完全无上下文迭代,我目前提供的最好是remap(cookbook)。请注意,重新映射没有glom的插件/注册功能,但是它确实可以开箱即用地迭代常见Python数据类型中的可糊路径,如this example所示(相应的glom
调用是在下面完成)。
我认为上面提到的the registration APIs中确实解决了这一问题。 glom()
关键字参数指的是内置操作,必须为所有类型都指定。
如果您“检索”的定义与内置get
注册有冲突,可以覆盖它,或可以指定可以针对其注册的新操作使用register_op
(例如,如何添加assign
操作)。
同样,很好的问题,您实际上是在这里利用Python的功能。希望这会有所帮助!