首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对象的YAML解析(PyYAML Python3)

对象的YAML解析(PyYAML Python3)
EN

Stack Overflow用户
提问于 2016-05-16 17:29:05
回答 2查看 2.2K关注 0票数 4

我有以下代码:

代码语言:javascript
复制
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:

代码语言:javascript
复制
!!python/object:v.Settings
annual_volatility_target: 0.25

问题是,当我加载settings时,没有设置settings.dailysettings.annual_volatility_target是,不管我在__init__中是否这么说。

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

我做错了什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-05-16 18:08:26

PyYAML中的Python对象是在两个步骤中构造的。首先调用__new__ (Constructor.make_python_instance()中),然后设置属性(在Constructor.set_python_instance_state()中)。这两个步骤是必要的,因为YAML支持对对象的引用,如果该对象是(间接的)自引用,则不能一次构造该对象,因为它所依赖的参数(包括它本身)还不可用。

你可以用两种方法解决这个问题。您可以为__setstate__()定义Settings,并使用dict调用它,并从__init__()调用它:

代码语言:javascript
复制
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)解决方案是在第一次访问时创建daily值:

代码语言:javascript
复制
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._daily中:

代码语言:javascript
复制
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
票数 1
EN

Stack Overflow用户

发布于 2016-05-16 18:06:23

一种可能是为构造函数编写一个Settings

代码语言:javascript
复制
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)

我必须使用一个修改过的yaml文件(我无法使它与注释!!python/object:v.Settings一起工作):

代码语言:javascript
复制
!v.Settings
annual_volatility_target: 0.25
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37259748

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档