gpt4 book ai didi

loadConfig 中的 Python/YAML : How to initialize additional objects not just from the YAML file,?

转载 作者:太空宇宙 更新时间:2023-11-03 15:23:05 24 4
gpt4 key购买 nike

我认为我对加载一些 YAML 对象有一个小误解。我在下面定义了类。

我想做的是使用 YAMLObjects 的重写 loadConfig 函数加载一些对象。其中一些来 self 的 .yaml 文件,但其他的应该由从 YAML 文件加载的对象构建。

例如,在下面的类中,我加载了一个名为“keep”的成员对象,它是一个字符串,命名要保留在该区域中的一些项目。但我也想将其解析为一个列表,并将该列表也存储为一个成员对象。而且我不希望用户必须在 YAML 中同时提供此参数的字符串和列表版本。

我目前的解决方法是重写 Region 中的 __getattr__ 函数,并让它在查找但找不到时创建默认值。但这比仅初始化对象所需的笨重和复杂。

我在这里误解了什么惯例。为什么 loadConfig 方法不创建 YAML 中找不到的其他内容?

import yaml, pdb

class Region(yaml.YAMLObject):
yaml_tag = u'!Region'

def __init__(self, name, keep, drop):
self.name = name
self.keep = keep
self.drop = drop

self.keep_list = self.keep.split("+")
self.drop_list = self.drop.split("+")
self.pattern = "+".join(self.keep_list) + "-" + "-".join(self.drop_list)
###

def loadConfig(self, yamlConfig):
yml = yaml.load_all(file(yamlConfig))
for data in yml:

# These get created fine
self.name = data["name"]
self.keep = data["keep"]
self.drop = data["drop"]

# These do not get created.
self.keep_list = self.keep.split("+")
self.drop_list = self.drop.split("+")
self.pattern = "+".join(self.keep_list) + "-" + "-".join(self.drop_list)
###
### End Region

if __name__ == "__main__":
my_yaml = "/home/path/to/test.yaml"
region_iterator = yaml.load_all(file(my_yaml))

# Set a debug breakpoint to play with region_iterator and
# confirm the extra stuff isn't created.
pdb.set_trace()

这里是 test.yaml 所以你可以运行所有这些并明白我的意思:

 Regions:

# Note: the string conventions below are for an
# existing system. This is a shortened, representative
# example.

Market1:
!Region
name: USAndGB
keep: US+GB
drop: !!null

Market2:
!Region
name: CanadaAndAustralia
keep: CA+AU
drop: !!null

例如,当我在 IPython shell 中运行它并探索加载的对象时,它看起来像这样:

In [57]: %run "/home/espears/testWorkspace/testRegions.py"
--Return--
> /home/espears/testWorkspace/testRegions.py(38)<module>()->None
-> pdb.set_trace()
(Pdb) region_iterator
<generator object load_all at 0x1139d820>
(Pdb) tmp = region_iterator.next()
(Pdb) tmp
{'Regions': {'Market2': <__main__.Region object at 0x1f858550>, 'Market1': <__main__.Region object at 0x11a91e50>}}
(Pdb) us = tmp['Regions']['Market1']
(Pdb) us
<__main__.Region object at 0x11a91e50>
(Pdb) us.name
'USAndGB'
(Pdb) us.keep
'US+GB'
(Pdb) us.keep_list
*** AttributeError: 'Region' object has no attribute 'keep_list'

最佳答案

我发现对于使用 yaml 处理基本上是存储类的有用模式是让加载器使用构造函数,以便以与正常创建对象时相同的方式创建对象。如果我理解您正在尝试正确执行的操作,那么这种结构可能会有用:

import inspect
import yaml
from collections import OrderedDict

class Serializable(yaml.YAMLObject):
__metaclass__ = yaml.YAMLObjectMetaclass
@property
def _dict(self):
dump_dict = OrderedDict()

for var in inspect.getargspec(self.__init__).args[1:]:
if getattr(self, var, None) is not None:
item = getattr(self, var)
if isinstance(item, np.ndarray) and item.ndim == 1:
item = list(item)
dump_dict[var] = item

return dump_dict

@classmethod
def to_yaml(cls, dumper, data):
return ordered_dump(dumper, '!{0}'.format(data.__class__.__name__),
data._dict)


@classmethod
def from_yaml(cls, loader, node):
fields = loader.construct_mapping(node, deep=True)
return cls(**fields)

def ordered_dump(dumper, tag, data):
value = []
node = yaml.nodes.MappingNode(tag, value)
for key, item in data.iteritems():
node_key = dumper.represent_data(key)
node_value = dumper.represent_data(item)
value.append((node_key, node_value))

return node

然后您可能希望您的 Region 类继承自 Serializable,并删除 loadConfig 内容。我发布的代码检查构造函数以查看要将哪些数据保存到 yaml 文件,然后在加载 yaml 文件时使用同一组数据调用构造函数。这样你只需要在你的构造函数中获得正确的逻辑并且 yaml 加载应该免费获得它。

该代码是从我的一个项目中删除的,如果它不能正常工作,请提前致歉。它也比需要的稍微复杂一些,因为我想通过使用 OrderedDict 来控制输出的顺序。您可以将我的 ordered_dump 函数替换为对 dumper.represent_dict 的调用。

关于loadConfig 中的 Python/YAML : How to initialize additional objects not just from the YAML file,?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11892736/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com