1

Let's say I have an app.py like this

class myClassA :
   def __init__(self):
      self.id = 100


class myClassB :
   def __init__(self, objA, id):
      pass

Is there a way to use hydra to have a config file like below work like it intuitively should ?

myClassA:
   _target_: myapp.myClassA


myclassB:
   _target_: myapp.myClassB
   param1: ${myClassA}
   param2: ${myclassB.param1.id}

My issue is that in order to instanciate my class B, I need an attribute from the class A object but this attribute is set in the init function of classA and cannot be set in the config file.

I've tried putting id: ??? but it didn't work

Thank a lot !

Aydin Abiar
  • 334
  • 3
  • 11

1 Answers1

0

The following does the trick:

# app.py
import hydra
from hydra.utils import instantiate
from omegaconf import OmegaConf

class myClassA:
    def __init__(self):
        self.id = 100

class myClassB:
    def __init__(self, objA, objA_id):
        assert isinstance(objA, myClassA)
        assert objA_id == 100
        print("myClassB __init__ ran")

@hydra.main(config_name="conf.yaml", config_path=".", version_base="1.2")
def app(cfg):
    instantiate(cfg)

if __name__ == "__main__":
    app()
# conf.yaml
myClassA:
   _target_: __main__.myClassA


myClassB:
   _target_: __main__.myClassB
   objA: ${myClassA}
   objA_id:
     _target_: builtins.getattr
     _args_:
     - ${myClassA}
     - "id"
$ python app.py
myClassB __init__ ran

How does this work? Using builtins.getattr as a target allows for looking up the "id" attribute on an instance of myClassA.

NOTE: Several instances of myClassA will be created here. There is an open feature request in Hydra regarding support for a singleton pattern in recursive instantiation, which would enable re-using the same instance of myClassA in several places.

Jasha
  • 5,507
  • 2
  • 33
  • 44