对对象的YAML解析(PyYAML-Python3)
我有以下代码:对对象的YAML解析(PyYAML-Python3),python,pyyaml,Python,Pyyaml,我有以下代码: class Settings: def __init__(self, annual_volatility_target): self.annual_volatility_target = annual_volatility_target self.daily = annual_volatility_target/np.sqrt(252) def yaml_load(name): with open('yaml/' + str(na
class Settings:
def __init__(self, annual_volatility_target):
self.annual_volatility_target = annual_volatility_target
self.daily = annual_volatility_target/np.sqrt(252)
def yaml_load(name):
with open('yaml/' + str(name) + '.yaml', 'r') as ymlfile:
return yaml.load(ymlfile)
settings = yaml_load("settings")
使用以下YAML:
!!python/object:v.Settings
annual_volatility_target: 0.25
问题是,当我加载设置时,设置。未设置每日设置<代码>设置。无论我是否在\uuuuu init\uuuu
中这样说,年度波动率目标都是
如果我手动实例化一个Settings
对象(即不使用PyYAML),它可以正常工作
我做错了什么?一种可能是为设置编写一个
import yaml
import numpy as np
class Settings:
def __init__(self, annual_volatility_target):
self.annual_volatility_target = annual_volatility_target
self.daily = annual_volatility_target/np.sqrt(252)
def yaml_load(name):
with open(str(name) + '.yaml', 'r') as ymlfile:
return yaml.load(ymlfile)
def settings_constructor(loader, node):
fields = loader.construct_mapping(node)
return Settings(fields['annual_volatility_target'])
yaml.add_constructor('!v.Settings', settings_constructor)
settings = yaml_load("settings")
print(settings.annual_volatility_target)
print(settings.daily)
!v.Settings
annual_volatility_target: 0.25
我必须使用一个修改过的yaml
文件(我无法使它与注释!!python/object:v.Settings
):
PyYAML中的Python对象是在两步过程中构造的。首先调用\uuuuu new\uuuuuu
(在构造函数中。生成python实例()
),然后设置属性(在构造函数中。设置python实例状态()
)。需要这两个步骤,因为YAML支持对对象的引用,如果该对象(间接地)是自引用的,则无法一次性构造该对象,因为它所依赖的参数(包括自身)还不可用
你可以用两种方法来解决这个问题。您可以为设置定义\uuuuuu setstate\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu()
,该设置将通过dict调用,并从\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
import yaml
yaml_str = """\
!!python/object:try.Settings
annual_volatility_target: 0.25
"""
class Settings:
def __init__(self, annual_volatility_target):
self.__setstate__({annual_volatility_target: annual_volatility_target})
def __setstate__(self, kw):
self.annual_volatility_target = kw.get('annual_volatility_target')
self.daily = self.annual_volatility_target/np.sqrt(252)
def __repr__(self):
return "Setting({}, {})".format(self.annual_volatility_target, self.daily)
settings = yaml.load(yaml_str)
print(settings)
另一个更通用(非PyYAML)的解决方案是在第一次访问时创建每日
值:
class Settings:
def __init__(self, annual_volatility_target):
self.annual_volatility_target = annual_volatility_target
@property:
def daily(self):
return annual_volatility_target/np.sqrt(252)
如果您经常访问daily
,则应在第一次计算值时将其缓存在例如self.\u daily
:
class Settings:
def __init__(self, annual_volatility_target):
self.annual_volatility_target = annual_volatility_target
self._daily = None
@property:
def daily(self):
if self._daily is None:
self._daily = annual_volatility_target/np.sqrt(252)
return self._daily
虽然第二个答案对我来说似乎更容易,但第一个答案更完整,包含了有价值的数据。@Srgrn哪一个是第一个,哪一个是第二个?我真蠢。你的是第一个。你不必写构造函数。PyYAML有内置机制(\uuu setstate\uuu
,子类化yaml.YAMLObject
)来处理对象加载。我使用了您的解决方案,但更进一步,删除了u init\uuu(),因为正如我所知,PyYAML从未调用过它。有什么理由让我把它留在里面吗?@cjm2671如果你想在测试例程等中实例化类的对象,有\uuu init\uuu()
会很有帮助,但你真的不必有它。