使用Python数据结构表示此的最佳方法

时间:2011-06-05 04:04:28

标签: python data-structures

  <specification> 
    <propertyName> string </propertyName>
    <value> 
      <number> 
        <value> anyNumberHere </value>
      </number>
      <text> 
        <value> anyTextHere </value>
      </text>
      <URL> 
        <value> anyURIHere </value>
      </URL>
    </value>
    <!-- ... 1 or more value nodes here ... -->
  </specification>
  <!-- ... 1 or more specification nodes here ... -->

我需要为API构建此请求,其中用户将传递这些值。那么,什么应该是表示这种情况的最佳方式,以便方法的用户可以轻松地将相应的值传递给操作?

我在想:

Dicts列表清单:

[specification1, specification2, specification3]

其中:

specification1= [value1, value2]

其中:

value1 = {number:anyNumberHere, text:anyTextHere, URL:anyURIHere}
value2 = {number:anyNumberHere, text:anyTextHere, URL:anyURIHere}

但是,我无法容纳:<propertyName>。有什么建议吗?

更重要的是,这听起来很复杂。我们可以像在Java中那样进行对象封装吗?我明白了,我们可以,但我很好奇,python中推荐的方式是什么?

My logic for now, suggestions (incorrect due to propertyName):
    #specification is a List of List of Dicts
    for spec in specification:
        specification_elem = etree.SubElement(root, "specification")
        propertyName_elem = etree.SubElement(specification_elem,"propertyName")
        propertyName_elem.text = spec_propertyName

        for value in spec:
            value_elem = etree.SubElement(specification_elem, "value")
            for key in value:
                key_elem = etree.SubElement(value_elem, key)
                keyValue_elem = etree.SubElement(key_elem, "value")
                keyValue_elem.text = value[key]

在这里,我将传递spec_propertyName作为diff参数。因此,用户将通过:specification and spec_propertyName

3 个答案:

答案 0 :(得分:6)

规范对象列表怎么样,每个对象都有一个property_name和一个value字典列表? (values可以是对象列表而不是字典。)

例如:

class Value(object):
    def __init__(self,
                 number=None,
                 text=None,
                 url=None):
        self.number = number
        self.text = text
        self.url = url

class Specification(object):
    def __init__(self, propertyName):
        self.propertyName = propertyName
        self.values = []

spec1 = Specification("Spec1")
spec1.values = [Value(number=3,
                      url="http://www.google.com"),
                Value(text="Hello, World!",
                      url="http://www.jasonfruit.com")]

spec2 = Specification("Spec2")
spec2.values = [Value(number=27,
                      text="I can haz cheezburger?",
                      url="http://stackoverflow.com"),
                Value(text="Running out of ideas.",
                      url="http://news.google.com")]

答案 1 :(得分:0)

如果propertyNames是唯一的,您可以拥有dict列表的dict。如果不是,则可以列出dict列表。

如果所有这些列表都难以跟踪,您可以创建一个类来存储数据:

class Specification:
    def __init__(self):
        self.propertyName = ""
        self.values = []

然后,使用:

spec = Specification()
spec.propertyName = "string"
value = {"URL":"someURI", "text":"someText"}
spec.values.append(value)

答案 2 :(得分:0)

这是使用named tuples的表示方法。您可以在闲暇时升级到使用类(添加代码以对调用者的输入进行一些验证,并允许省略field=None用于可选字段),而无需对用户API进行任何其他更改,并且对ElementTree的更改很少 - 建筑代码。

# -*- coding: cp1252 -*-

from collections import namedtuple
import xml.etree.cElementTree as etree

Specifications = namedtuple('Specifications', 'specification_list')
Specification = namedtuple('Specification', 'propertyName value_list')
Value = namedtuple('Value', 'number text url')

def make_etree(specifications, encoding):
    """ 
    Convert user's `specifications` to an ElementTree.
    `encoding` is encoding of *input* `str` objects.
    """
    def ensure_unicode(v):
        if isinstance(v, str): return v.decode(encoding)
        if isinstance(v, unicode): return v
        return unicode(v) # convert numbers etc to unicode strings  

    root = etree.Element('specifications')
    for spec in specifications.specification_list:
        specification_elem = etree.SubElement(root, "specification")
        propertyName_elem = etree.SubElement(specification_elem, "propertyName")
        propertyName_elem.text = ensure_unicode(spec.propertyName)
        for value in spec.value_list:
            value_elem = etree.SubElement(specification_elem, "value")
            for key in value._fields:
                kv = getattr(value, key)
                if kv is None: continue
                key_elem = etree.SubElement(value_elem, key)
                keyValue_elem = etree.SubElement(key_elem, "value")
                keyValue_elem.text = ensure_unicode(kv)
    return etree.ElementTree(root)

# === sample caller code follows ===

specs = Specifications(
    specification_list=[
        Specification(
            propertyName='a prop',
            value_list=[
                Value(
                    number=42,
                    text='universe', 
                    url='http://uww.everywhere',
                    ),
                Value(
                    number=0,
                    text=None, # optional
                    url='file:///dev/null',
                    ),
                ],
            ),
        Specification(
            propertyName='b prop',
            value_list=[
                Value(
                    number=1,
                    text='Üñîçøðè', # str object, encoded in cp1252
                    url=u'Üñîçøðè', # unicode object
                    ),
                ],           
            ),
        ],
    )

print repr(specs); print

import sys
tree = make_etree(specs, 'cp1252')
import cStringIO
f = cStringIO.StringIO()
tree.write(f, encoding='UTF-8', xml_declaration=True)
print repr(f.getvalue())
print

输出(在第80列折叠):

Specifications(specification_list=[Specification(propertyName='a prop', value_li
st=[Value(number=42, text='universe', url='http://uww.everywhere'), Value(number
=0, text=None, url='file:///dev/null')]), Specification(propertyName='b prop', v
alue_list=[Value(number=1, text='\xdc\xf1\xee\xe7\xf8\xf0\xe8', url=u'\xdc\xf1\x
ee\xe7\xf8\xf0\xe8')])])

"<?xml version='1.0' encoding='UTF-8'?>\n<specifications><specification><propert
yName>a prop</propertyName><value><number><value>42</value></number><text><value
>universe</value></text><url><value>http://uww.everywhere</value></url></value><
value><number><value>0</value></number><url><value>file:///dev/null</value></url
></value></specification><specification><propertyName>b prop</propertyName><valu
e><number><value>1</value></number><text><value>\xc3\x9c\xc3\xb1\xc3\xae\xc3\xa7
\xc3\xb8\xc3\xb0\xc3\xa8</value></text><url><value>\xc3\x9c\xc3\xb1\xc3\xae\xc3\
xa7\xc3\xb8\xc3\xb0\xc3\xa8</value></url></value></specification></specification
s>"