9

我无法以我想要的 python 形式获取数据。

基本上我有一个程序可以读取二进制数据并提供对所述数据进行绘图和分析的功能。

我的数据有主标题,然后是子标题,可以是任意数量的不同数据类型。

我希望能够访问我的数据,例如:

>>> a = myDatafile.readit()
>>> a.elements.hydrogen.distributionfunction
(a big array)
>>> a.elements.hydrogen.mass
1
>>> a.elements.carbon.mass
12

但直到运行时我才知道原子的名称。

我试过使用namedtuple,例如在我读完所有原子名称之后:

self.elements = namedtuple('elements',elementlist)

其中 elementlist 是字符串列表,例如 ('hydrogen','carbon')。但问题是我不能使用例如嵌套这些:

for i in range(0,self.nelements):
    self.elements[i] = namedtuple('details',['ux','uy','uz','mass','distributionfunction'])

然后能够通过例如访问这些值

self.elements.electron.distributionfunction.

也许我这样做完全错了。我对python相当缺乏经验。我知道如果我不关心动态命名变量,这将很容易做到。

我希望我已经明确了我想要实现的目标!

4

4 回答 4

5

在不知道您的数据的情况下,我们只能给出一个通用的解决方案。

考虑到前两行包含标题和子标题以某种方式读取它,您确定了层次结构。您所要做的就是创建一个分层字典。

例如,扩展您的示例

data.elements.hydrogen.distributionfunction
data.elements.nitrogen.xyzfunction
data.elements.nitrogen.distributionfunction
data.compound.water.distributionfunction
data.compound.hcl.xyzfunction

所以我们必须像这样创建一个字典

{'data':{'elements':{'hydrogen':{'distributionfunction':<something>}
                     'nitrogen':{'xyzfunction':<something>,
                           'distributionfunction':<something>}
                }
       compound:{'water':{'distributionfunction':<something>}
                 'hcl':{'xyzfunction':<something>}
                }
       }
 }

你将如何填充字典取决于现在很难说的数据。但是您应该从标题中填充字典的键,并且您必须以某种方式将数据映射到字典的空槽中的相应值。

填充地图后,您可以访问它

 yourDict['data']['compound']['hcl']['xyzfunction']
于 2011-12-05T17:06:21.203 回答
3

如果您的元素名称是动态的并且在运行时从数据中获取,您可以将它们分配给一个 dict 并像这样访问

elements['hydrogen'].mass

但是如果你想要点符号,你可以在运行时创建属性,例如

from collections import namedtuple

class Elements(object):
    def add_element(self, elementname, element):
        setattr(self, elementname, element)

Element = namedtuple('Element', ['ux','uy','uz','mass','distributionfunction'])

elements = Elements()
for data in [('hydrogen',1,1,1,1,1), ('helium',2,2,2,2,2), ('carbon',3,3,3,3,3)]:
    elementname = data[0]
    element = Element._make(data[1:])
    elements.add_element(elementname, element)

print elements.hydrogen.mass
print elements.carbon.distributionfunction

在这里,我假设您拥有数据,但是对于任何其他格式的数据,您都可以执行类似的技巧

于 2011-12-05T17:09:14.610 回答
2

这是一种从嵌套数据递归创建命名元组的方法。

from collections import Mapping, namedtuple


def namedtuplify(mapping, name='NT'):  # thank you https://gist.github.com/hangtwenty/5960435
    """ Convert mappings to namedtuples recursively. """
    if isinstance(mapping, Mapping):
        for key, value in list(mapping.items()):
            mapping[key] = namedtuplify(value)
        return namedtuple_wrapper(name, **mapping)
    elif isinstance(mapping, list):
        return [namedtuplify(item) for item in mapping]
    return mapping

def namedtuple_wrapper(name, **kwargs):
    wrap = namedtuple(name, kwargs)
    return wrap(**kwargs)


stuff = {'data': {'elements': {'hydrogen': {'distributionfunction': 'foo'}, 
  'nitrogen': {'xyzfunction': 'bar', 
    'distributionfunction': 'baz'}
  },
  'compound': {'water': {'distributionfunction': 'lorem'}, 
    'hcl': {'xyzfunction': 'ipsum'}}}
 }

example = namedtuplify(stuff)

example.data.elements.hydrogen.distributionfunction  # 'foo'
于 2016-08-31T03:06:30.093 回答
0

我对嵌套的 json 有同样的问题,但需要能够用 pickle 序列化输出,这不喜欢你动态创建对象。

我接受了@bren 的回答并对其进行了增强,以便生成的结构可以用pickle 序列化。您必须将对您创建的每个结构的引用保存到全局变量中,以便 pickle 可以密切关注它们。

##############################################
class Json2Struct:
    '''
    Convert mappings to nested namedtuples

    Usage:
        jStruct = Json2Struct('JS').json2Struct(json)
    '''
##############################################

    def __init__(self, name):
        self.namePrefix = name
        self.nameSuffix = 0


    def json2Struct(self, jsonObj):  # thank you https://gist.github.com/hangtwenty/5960435
        """ 
        Convert mappings to namedtuples recursively. 
        """
        if isinstance(jsonObj, Mapping):
            for key, value in list(jsonObj.items()):
                jsonObj[key] = self.json2Struct(value)
            return self.namedtuple_wrapper(**jsonObj)
        elif isinstance(jsonObj, list):
            return [self.json2Struct(item) for item in jsonObj]
        return jsonObj


    def namedtuple_wrapper(self, **kwargs):
        self.nameSuffix += 1
        name = self.namePrefix + str(self.nameSuffix)

        Jstruct = namedtuple(name, kwargs)
        globals()[name] = Jstruct

        return Jstruct(**kwargs)

下面的示例应该如下工作并且也是可序列化的:

stuff = {'data': {'elements': {'hydrogen': {'distributionfunction': 'foo'}, 
  'nitrogen': {'xyzfunction': 'bar', 
    'distributionfunction': 'baz'}
  },
  'compound': {'water': {'distributionfunction': 'lorem'}, 
    'hcl': {'xyzfunction': 'ipsum'}}}
 }

example = Json2Struct('JS').json2Struct(stuff)

example.data.elements.hydrogen.distributionfunction  # 'foo'
于 2016-11-17T17:45:51.597 回答