Frage

Ich habe folgendes Python 2.6 Programm und YAML Definition (mit PyYAML ):

import yaml

x = yaml.load(
    """
        product:
           name     : 'Product X'
           sku      : 123
           features :
             - size    :  '10x30cm'
               weight  :  '10kg'

         """
    )

print type(x)
print x


Welche Ergebnisse in der folgenden Ausgabe:
<type 'dict'>
{'product': {'sku': 123, 'name': 'Product X', 'features': [{'weight': '10kg', 'size': '10x30cm'}]}}

Es ist möglich, ein Objekt mit Feldern von x zu erstellen?

Ich würde auf die folgende mögen:

print x.features[0].size

Ich bin mir bewusst, dass es möglich ist, zu erstellen und die Instanz von einer vorhandenen Klasse, aber das ist nicht das, was ich für dieses spezielle Szenario möge.

Edit:

  • Aktualisiert das verwirrende Teil über eine ‚stark typisierte Objekt‘.
  • Changed Zugriff auf features auf einen Indexer wie vorgeschlagen Alex Martelli
War es hilfreich?

Lösung

Sie haben also ein Wörterbuch mit String-Schlüssel und Werte, die Zahlen sein können, verschachtelte Wörterbücher, Listen und Sie möchten, dass in eine Instanz wickeln, die Sie verwenden Attribut Zugriff anstelle von dict Indizierung lässt, und „Anruf mit ein Index“anstelle der Liste Indizierung - nicht sicher, was‚stark typisierte‘hat damit zu tun, oder warum Sie denken, .features(0) besser ist als .features[0] (wie ein natürlicher Weg, um eine Liste zu indizieren!), aber sicher, es ist möglich. Zum Beispiel könnte ein einfacher Ansatz sein:

def wrap(datum):
  # don't wrap strings
  if isinstance(datum, basestring):
    return datum
  # don't wrap numbers, either
  try: return datum + 0
  except TypeError: pass
  return Fourie(datum)

class Fourie(object):
  def __init__(self, data):
    self._data = data
  def __getattr__(self, n):
    return wrap(self._data[n])
  def __call__(self, n):
    return wrap(self._data[n])

So x = wrap(x['product']) sollten Sie geben Ihren Wunsch (warum Sie dieses Niveau überspringen möchten, wenn Ihre allgemeine Logik offensichtlich x.product.features(0).size erfordern würde, ich habe keine Ahnung, aber deutlich, dass das Überspringen der besser an der Stelle der Anruf angewendet anstatt hartcodiert in der Wrapper-Klasse oder die Wrapper Fabrik Funktion ich gerade gezeigt habe).

Bearbeiten : wie die OP sagt er will features[0] tut anstatt features(0), nur die letzten beiden Zeilen ändern

  def __getitem__(self, n):
    return wrap(self._data[n])

d. Definieren __getitem__ (die magische Methode Indizierung Underlying) statt __call__ (die magische Methode zugrunde liegende Instanz-Call).

Die Alternative zu „einer vorhandenen Klasse“ (hier Fourie) wäre eine neue Klasse im Fluge auf introspecting des umwickelten dict basierend zu schaffen - machbar, auch, aber ernst dunkelgrau, wenn nicht schwarz , Magie und ohne wirklichen operativen Vorteil, dass ich mich vorstellen kann.

Wenn das OP genau klären, warum er von dem Erstellen von Klassen im Fluge nach den Meta-Programmierung Spitzen sehnt sein kann, welcher Vorteil er glaubt, dass er auf diese Weise sein könnte bekommen, etc, werde ich zeigen, wie es zu tun (und zeigen, wahrscheinlich werde ich auch, warum die craved-for Vorteil wird nicht in der Tat da sein ;-). Aber Einfachheit ist eine wichtige Qualität in jeder Programmier Bemühungen und der „tiefen dunklen Magie“ zu verwenden, wenn einfache, unkomplizierte Code wie die oben funktioniert gut, ist in der Regel nicht die besten Ideen! -)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top