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

-1 投票
3 回答
512 浏览
提问于 2025-04-16 18:58
  <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请求,用户会传入这些值。那么,怎样表示这些值才能让使用这个方法的用户更容易传递相应的值呢?

我在想:

列表的列表的字典:

[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作为一个不同的参数传递。所以,用户将传入:specification和spec_propertyName

3 个回答

0

如果属性名称是唯一的,你可以用一个字典来存储字典的列表。如果属性名称不是唯一的,你就可以用一个列表来存储列表的列表,再加上字典。

如果这些列表让你觉得很难管理,你可以创建一个类来存储这些数据:

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

然后,使用:

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

这里介绍了一种使用 命名元组 的表示方法。你可以随时升级到使用类(这样可以添加一些代码来验证用户输入的内容,并且允许在可选字段中省略 field=None),这样对用户接口没有其他影响,构建 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>"
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")]

撰写回答