Лучший способ представить это, используя структуры данных Python

1
  <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 в качестве параметра diff. Итак, пользователь будет передавать: specification and spec_propertyName

  • 0
    Должны ли быть указаны все три?
  • 0
    Это зависит от того, могут ли присутствовать все 3 или только 1 числа, текст и URL.
Теги:
data-structures

3 ответа

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")]
  • 0
    какие-нибудь стартеры о том, как это сделать?
  • 0
    @zengr - я добавил для тебя стартер.
Показать ещё 1 комментарий
0

Здесь представлен подход представления с использованием названных кортежей. Вы можете перейти на использование классов (добавив код, чтобы выполнить некоторую проверку на входе вызывающего абонента и разрешить пропуски 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 `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>"
  • 0
    Это интересный вариант - я не замечал именованных кортежей раньше.
0

Если propertyNames уникальны, вы можете получить список 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)
  • 0
    propertyNames является уникальным для спецификации. Там может быть несколько спецификаций.
  • 0
    о, я вижу ... да, я думаю, что объектный подход был бы лучше здесь, чтобы уменьшить путаницу.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню