PyYAML 解析为任意对象
我有以下 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': '产品 X', 'features': [{'weight': '10kg', 'size': '10x30cm'}]}}
可以使用 x
中的字段创建对象吗?
我想要以下内容:
print x.features[0].size
我知道可以从现有类创建和实例化,但是对于这个特定场景,这不是我想要的。
编辑:
- 更新了有关“强类型对象”的令人困惑的部分。
- 按照 Alex Martelli 的建议,将对
features
的访问权限更改为索引器
I have the following Python 2.6 program and YAML definition (using PyYAML):
import yaml
x = yaml.load(
"""
product:
name : 'Product X'
sku : 123
features :
- size : '10x30cm'
weight : '10kg'
"""
)
print type(x)
print x
Which results in the following output:<type 'dict'>
{'product': {'sku': 123, 'name': 'Product X', 'features': [{'weight': '10kg', 'size': '10x30cm'}]}}
It is possible to create an object with fields from x
?
I would like to the following:
print x.features[0].size
I am aware that it is possible to create and instance from an existing class, but that is not what I want for this particular scenario.
Edit:
- Updated the confusing part about a 'strongly typed object'.
- Changed access to
features
to a indexer as suggested Alex Martelli
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
因此,您有一个带有字符串键和值的字典,可以是数字、嵌套字典、列表,并且您希望将其包装到一个实例中,该实例允许您使用属性访问来代替字典索引和“使用索引调用”代替列表索引 - 不确定“强类型”与此有何关系,或者为什么您认为
.features(0)
比.features[0]
更好> (这是一种更自然的索引列表的方式!),但是,当然,这是可行的。例如,一个简单的方法可能是:所以
x = wrap(x['product'])
应该满足您的愿望(当您的整体逻辑显然需要时,为什么您想跳过该级别>x.product.features(0).size
,我不知道,但显然,跳过更好地应用于调用点,而不是在包装类或我刚刚的包装工厂函数中硬编码所示)。编辑:正如OP所说,他确实想要
features[0]
而不是features(0)
,只需将最后两行更改为,即定义
__getitem__
(索引底层的魔术方法)而不是__call__
(实例调用底层的魔术方法)。“现有类”(此处为
Fourie
)的替代方案是基于内省包装的字典动态创建一个新类 - 也是可行的,但如果不可行,则会严重呈深灰色实际上黑色,魔法,并且没有任何我能想到的真正的操作优势。如果OP能够准确地澄清为什么他可能渴望在动态创建类的元编程高峰之后,他认为他可能会获得什么优势,等等,我将展示如何做到这一点(并且可能,我还将说明为什么人们渴望的优势实际上不存在;-)。但简单性在任何编程工作中都是一个重要的品质,当像上面这样简单、直接的代码工作得很好时,使用“深层黑暗魔法”通常不是最好的想法!-)
So you have a dictionary with string keys and values that can be numbers, nested dictionaries, lists, and you'd like to wrap that into an instance which lets you use attribute access in lieu of dict indexing, and "call with an index" in lieu of list indexing -- not sure what "strongly typed" has to do with this, or why you think
.features(0)
is better than.features[0]
(such a more natural way to index a list!), but, sure, it's feasible. For example, a simple approach might be:So
x = wrap(x['product'])
should give you your wish (why you want to skip that level when your overall logic would obviously requirex.product.features(0).size
, I have no idea, but clearly that skipping's better applied at the point of call rather than hard-coded in the wrapper class or the wrapper factory function I've just shown).Edit: as the OP says he does want
features[0]
rather thanfeatures(0)
, just change the last two lines toi.e., define
__getitem__
(the magic method underlying indexing) instead of__call__
(the magic method underlying instance-call).The alternative to "an existing class" (here,
Fourie
) would be to create a new class on the fly based on introspecting the wrapped dict -- feasible, too, but seriously dark-gray, if not actually black, magic, and without any real operational advantage that I can think of.If the OP can clarify exactly why he may be hankering after the meta-programming peaks of creating classes on the fly, what advantage he believes he might be getting that way, etc, I'll show how to do it (and, probably, I'll also show why the craved-for advantage will not in fact be there;-). But simplicity is an important quality in any programming endeavor, and using "deep dark magic" when plain, straightforward code like the above works just fine, is generally not the best of ideas!-)