YAML解析为对象(PyYAML Python3)

我有以下代码:

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

问题是,当我加载设置时,settings.daily未设置. settings.annual_volatility_target是,无论我是否在__init__中这么说.

如果我手动实例化一个Settings对象(即不使用PyYAML),它可以正常工作.

我究竟做错了什么?

最佳答案 PyYAML中的Python对象分两步构建.首先调用__new__(在Constructor.make_python_instance()中),然后设置属性(在Constructor.set_python_instance_state()中).这个两步过程是必需的,因为YAML支持对对象的引用,并且如果该对象是(间接)自引用的,则它不能一次构造,因为它依赖的参数(包括它自己)尚不可用.

您可以通过两种方式解决此问题.您可以为Settings定义__setstate __(),并使用dict调用它,并从__init __()调用它:

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)

如果您经常每天访问,那么您应该将其缓存在例如self._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
点赞