I've got the following code:
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")
With the following YAML:
!!python/object:v.Settings
annual_volatility_target: 0.25
The problem is, when I load settings
, settings.daily
isn't set. settings.annual_volatility_target
is, regardless of whether I say so in __init__
or not.
If I instantiate a Settings
object manually (i.e. not using PyYAML), it works fine.
What am I doing wrong?
One possibility is to write a constructor for
Settings
:I have to use a modified
yaml
file (I was unable to make it work with annotation!!python/object:v.Settings
):Python objects in PyYAML are constructed in a two step process. First
__new__
is called (inConstructor.make_python_instance()
) and then the attributes are set (inConstructor.set_python_instance_state()
). This two step process is needed because YAML supports references to objects and if that object is (indirectly) self referential it cannot be constructed in one go, because the parameters on which it depends (which include itself) are not available yet.You can solve this in two ways. You can define
__setstate__()
forSettings
and that will be called with adict
and call this from__init__()
as well:Another, and more general (non PyYAML) solution is to create the
daily
value on first access:If you access
daily
often, then you should cache it in e.g.self._daily
the first time you calculate the value: