У меня есть следующая программа Python 2.6 и определение YAML (использующий PyYAML):
import yaml
x = yaml.load(
"""
product:
name : 'Product X'
sku : 123
features :
- size : '10x30cm'
weight : '10kg'
"""
)
print type(x)
print x
Который приводит к следующему выводу:
{'product': {'sku': 123, 'name': 'Product X', 'features': [{'weight': '10kg', 'size': '10x30cm'}]}}
Возможно создать объект с полями от x
?
Я хотел бы к следующему:
print x.features[0].size
Я знаю, что возможно создать и инстанцировать от существующего класса, но это не то, что я хочу для этого конкретного сценария.
Править:
features
к индексатору как предложенный Alex Martelli Итак, у вас есть словарь со строковыми ключами и значениями, которые могут быть числами, вложенными словарями, списками, и вы хотите обернуть его в экземпляр, который позволяет использовать доступ к атрибутам вместо индексации dict и «вызов с индексом» вместо индексации списка - не уверен, какое отношение к этому имеет «строго типизированный» или почему вы думаете .features (0)
лучше, чем .features [0]
(такой более естественный способ индексирования списка!), Но, конечно, это возможно. Например, простой подход может быть таким:
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])
Итак x = wrap (x ['product'])
должен дать вам ваше желание (почему вы хотите пропустить этот уровень, когда ваша общая логика, очевидно, потребует x.product.features (0).size
, я понятия не имею, но ясно, что пропуск лучше применять в точке вызова, а не жестко закодировать в классе оболочки или функции фабрики оболочки, которую я только что показал).
Правка : поскольку ОП говорит, что ему нужны функции [0]
, а не функции (0)
, просто измените последние две строки на
def __getitem__(self, n):
return wrap(self._data[n])
, т. Е. define __ getitem __
(магический метод, лежащий в основе индексации) вместо __ call __
(магический метод, лежащий в основе вызова экземпляра).
Альтернативой «существующему классу» (здесь Fourie
) было бы создание нового класса «на лету» на основе самоанализа обернутого dict - тоже возможно, но серьезно темно-серое, если не на самом деле черный , магический, и без какого-либо реального оперативного преимущества, о котором я могу думать.
Если ОП может точно прояснить, почему он может стремиться к пикам метапрограммирования создания классов на лету, какие преимущества, по его мнению, он может получить таким образом и т. Д., Я покажу, как это сделать (и , наверное, я также покажу, почему желанного преимущества не будет , на самом деле ;-). Но простота - важное качество в любом начинании программирования, и использование «глубокой темной магии», когда простой и понятный код, подобный приведенному выше, работает нормально, как правило, не лучшая идея! -)