Sus*_*ser 8 python json metaprogramming
我正在使用python 2.7中嵌套的类似JSON的数据结构,我用一些外来的perl代码进行交换.我只想以amore pythonic方式"使用"这些列表和字典的嵌套结构.
所以如果我有这样的结构......
a = {
'x': 4,
'y': [2, 3, { 'a': 55, 'b': 66 }],
}
Run Code Online (Sandbox Code Playgroud)
...我希望能够在python脚本中处理它,就好像它是嵌套的python classes/Structs一样,如下所示:
>>> aa = j2p(a) # <<- this is what I'm after.
>>> print aa.x
4
>>> aa.z = 99
>>> print a
{
'x': 4,
'y': [2, 3, { 'a': 55, 'b': 66 }],
'z': 99
}
>>> aa.y[2].b = 999
>>> print a
{
'x': 4,
'y': [2, 3, { 'a': 55, 'b': 999 }],
'z': 99
}
Run Code Online (Sandbox Code Playgroud)
因此,aa是原始结构的代理.这是我到目前为止所提出的,受到Python中优秀什么是元类的启发?题.
def j2p(x):
"""j2p creates a pythonic interface to nested arrays and
dictionaries, as returned by json readers.
>>> a = { 'x':[5,8], 'y':5}
>>> aa = j2p(a)
>>> aa.y=7
>>> print a
{'x': [5, 8], 'y':7}
>>> aa.x[1]=99
>>> print a
{'x': [5, 99], 'y':7}
>>> aa.x[0] = {'g':5, 'h':9}
>>> print a
{'x': [ {'g':5, 'h':9} , 99], 'y':7}
>>> print aa.x[0].g
5
"""
if isinstance(x, list):
return _list_proxy(x)
elif isinstance(x, dict):
return _dict_proxy(x)
else:
return x
class _list_proxy(object):
def __init__(self, proxied_list):
object.__setattr__(self, 'data', proxied_list)
def __getitem__(self, a):
return j2p(object.__getattribute__(self, 'data').__getitem__(a))
def __setitem__(self, a, v):
return object.__getattribute__(self, 'data').__setitem__(a, v)
class _dict_proxy(_list_proxy):
def __init__(self, proxied_dict):
_list_proxy.__init__(self, proxied_dict)
def __getattribute__(self, a):
return j2p(object.__getattribute__(self, 'data').__getitem__(a))
def __setattr__(self, a, v):
return object.__getattribute__(self, 'data').__setitem__(a, v)
def p2j(x):
"""p2j gives back the underlying json-ic json-ic nested
dictionary/list structure of an object or attribute created with
j2p.
"""
if isinstance(x, (_list_proxy, _dict_proxy)):
return object.__getattribute__(x, 'data')
else:
return x
Run Code Online (Sandbox Code Playgroud)
现在我想知道是否有一种优雅的方法来映射一整套__*__特殊功能,比如__iter__,__delitem__?所以我不需要使用p2j()迭代或做其他pythonic东西来解开东西.
# today:
for i in p2j(aa.y):
print i
# would like to...
for i in aa.y:
print i
Run Code Online (Sandbox Code Playgroud)
Tho*_*s K 12
我认为你让它变得比它需要的更复杂.如果我理解正确的话,你应该做的就是:
import json
class Struct(dict):
def __getattr__(self, name):
return self[name]
def __setattr__(self, name, value):
self[name] = value
def __delattr__(self, name):
del self[name]
j = '{"y": [2, 3, {"a": 55, "b": 66}], "x": 4}'
aa = json.loads(j, object_hook=Struct)
for i in aa.y:
print(i)
Run Code Online (Sandbox Code Playgroud)
加载JSON时,该object_hook参数允许您指定可调用对象来处理它加载的对象.我刚刚使用它将dict转换为允许属性访问其键的对象.文件
有一个 attrdict 库可以以非常安全的方式完成此操作,但如果您愿意,此答案中给出了一种快速而肮脏(可能泄漏内存)的方法:
class AttrDict(dict):
def __init__(self, *args, **kwargs):
super(AttrDict, self).__init__(*args, **kwargs)
self.__dict__ = self
j = '{"y": [2, 3, {"a": 55, "b": 66}], "x": 4}'
aa = json.loads(j, object_hook=AttrDict)
Run Code Online (Sandbox Code Playgroud)