Skip to content

Commit

Permalink
updated instantiate documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
omry committed Sep 25, 2020
1 parent 8343d38 commit e4ac92b
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 41 deletions.
8 changes: 4 additions & 4 deletions hydra/_internal/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,7 @@ def _get_kwargs(
config: Union[DictConfig, ListConfig],
**kwargs: Any,
) -> Any:
from hydra.utils import _call
from hydra.utils import instantiate

assert OmegaConf.is_config(config)

Expand All @@ -602,12 +602,12 @@ def _get_kwargs(
if recursive:
for k, v in final_kwargs.items():
if _is_target(v):
final_kwargs[k] = _call(v)
final_kwargs[k] = instantiate(v)
elif OmegaConf.is_dict(v) and not OmegaConf.is_none(v):
d = OmegaConf.create({}, flags={"allow_objects": True})
for key, value in v.items():
if _is_target(value):
d[key] = _call(value)
d[key] = instantiate(value)
elif OmegaConf.is_config(value):
d[key] = _get_kwargs(value)
else:
Expand All @@ -617,7 +617,7 @@ def _get_kwargs(
lst = OmegaConf.create([], flags={"allow_objects": True})
for x in v:
if _is_target(x):
lst.append(_call(x))
lst.append(instantiate(x))
elif OmegaConf.is_config(x):
lst.append(_get_kwargs(x))
else:
Expand Down
29 changes: 16 additions & 13 deletions hydra/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,21 @@
log = logging.getLogger(__name__)


def call(config: Any, *args: Any, **kwargs: Any) -> Any:
return _call(config, *args, **kwargs)


def _call(config: Any, *args: Any, **kwargs: Any) -> Any:
def instantiate(config: Any, *args: Any, **kwargs: Any) -> Any:
"""
:param config: An object describing what to call and what params to use.
_target_ : str : Mandatory target (class name, function name etc)
_recursive_: bool = True : recursive instantiation, defaults to True
:param args: optional positional parameters pass-through
:param kwargs: optional named parameters pass-through
:return: the return value from the specified class or method
:param config: An config object describing what to call and what params to use.
In addition to the parameters, the config must contain:
_target_ : target class or callable name (str)
_recursive_: Construct nested objects as well (bool).
True by default.
may be overridden via a _recursive_ key in
the kwargs
:param args: Optional positional parameters pass-through
:param kwargs: Optional named parameters to override
parameters in the config object. Parameters not present
in the config objects are being passed as is to the target.
:return: if _target_ is a class name: the instantiated object
if _target_ is a callable: the return value of the call
"""

if OmegaConf.is_none(config):
Expand Down Expand Up @@ -70,8 +73,8 @@ def _call(config: Any, *args: Any, **kwargs: Any) -> Any:
raise type(e)(f"Error instantiating/calling '{cls}' : {e}")


# Alias for call
instantiate = call
# Alias for instantiate
call = instantiate


def get_class(path: str) -> type:
Expand Down
2 changes: 1 addition & 1 deletion website/docs/patterns/instantiate_objects/config_files.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ id: config_files
title: Config files example
sidebar_label: Config files example
---
[![Example application](https://img.shields.io/badge/-Example%20application-informational)](https://github.com/facebookresearch/hydra/tree/master/examples/instantiate/object)
[![Example applications](https://img.shields.io/badge/-Example%20applications-informational)](https://github.com/facebookresearch/hydra/tree/master/examples/instantiate)

This example demonstrates the use of config files to instantiated objects.

Expand Down
116 changes: 94 additions & 22 deletions website/docs/patterns/instantiate_objects/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,55 @@ id: overview
title: Instantiating objects with Hydra
sidebar_label: Overview
---
[![Example applications](https://img.shields.io/badge/-Example%20applications-informational)](https://github.com/facebookresearch/hydra/tree/master/examples/instantiate)

One of the best ways to drive different behavior in an application is to instantiate different implementations of an interface.
The code using the instantiated object only knows the interface which remains constant, but the behavior
is determined by the actual object instance.

Hydra provides `hydra.utils.call()` (and its alias `hydra.utils.instantiate()`) for instantiating objects and calling functions. Prefer `instantiate` for creating objects and `call` for invoking functions.
Hydra provides `hydra.utils.instantiate()` (and its alias `hydra.utils.call()`) for instantiating objects and calling functions. Prefer `instantiate` for creating objects and `call` for invoking functions.

Call/instantiate supports:
- Class names : Call the `__init__` method
- Callables like functions, static functions, class methods and objects
- Constructing an object by calling the `__init__` method
- Calling functions, static functions, class methods and other callable global objects

```python
def call(config: Any, *args: Any, **kwargs: Any) -> Any:
def instantiate(config: Any, *args: Any, **kwargs: Any) -> Any:
"""
:param config: An object describing what to call and what params to use.
Must have a _target_ field.
:param args: optional positional parameters pass-through
:param kwargs: optional named parameters pass-through
:return: the return value from the specified class or method
:param config: An config object describing what to call and what params to use.
In addition to the parameters, the config must contain:
_target_ : target class or callable name (str)
_recursive_: Construct nested objects as well (bool).
True by default.
may be overridden via a _recursive_ key in
the kwargs
:param args: Optional positional parameters pass-through
:param kwargs: Optional named parameters to override
parameters in the config object. Parameters not present
in the config objects are being passed as is to the target.
:return: if _target_ is a class name: the instantiated object
if _target_ is a callable: the return value of the call
"""
...

# Alias for call
instantiate = call
# Alias for instantiate
call = instantiate
```

The config passed to these functions must have a key called `_target_`, with the value of a fully qualified class name, class method, static method or callable.
Any additional parameters are passed as keyword arguments to tha target.

For example, your application may have a User class that looks like this:
### Simple usage

Your application may have a User class that looks like this:
```python title="user.py"
class User:
name: str
age : int
code : int

def __init__(self, name: str, age: int):
def __init__(self, name: str, code: int):
self.name = name
self.age = age
self.code = code
```

<div className="row">
Expand All @@ -51,7 +62,13 @@ class User:
bond:
_target_: user.User
name: Bond
age: 7
code: 7






```


Expand All @@ -61,16 +78,71 @@ bond:

```python title="Instantiation"
user : User = instantiate(cfg.bond)
assert isinstance(user, user.User)
assert user.name == "Bond"
assert user.age == 7
# User(name="Bond", code=7)

# Overriding the config on the callsite
user : User = instantiate(cfg.bond,
name="Batman")
# User(name="Batman", code=7)

# None config -> None result
assert instantiate(None) is None
```

</div>
</div>


For convenience, instantiate/call returns `None` when receiving `None` as input.
```python
assert instantiate(None) is None
### Recursive instantiation
Sometime it's useful to instantiate nested objects. Your app may have a class for a group of users:
```python title="group.py"
class Group:
name: str
users: List[User]

def __init__(self, name: str, users: List[User]):
self.name = name
self.users = users
```


<div className="row">

<div className="col col--6">

```yaml title="Config"
group:
_target_: group.Group
name: Super heroes
users:
- _target_: user.User
name: Batman
code: 100
- _target_: user.User
name: Wolverine
code: 666


```

</div>

<div className="col col--6">

```python title="Instantiation"
group: Group = instantiate(cfg.group)
# Group(
# name="Super heroes",
# users=[
# User(name="Batman", code=100),
# User(name="Wolverine", code=666)
# ]
# )




```

</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ title: Structured Configs example
sidebar_label: Structured Configs example
---

[![Example application](https://img.shields.io/badge/-Example%20application-informational)](https://github.com/facebookresearch/hydra/tree/master/examples/instantiate/schema/my_app.py)
[![Example applications](https://img.shields.io/badge/-Example%20applications-informational)](https://github.com/facebookresearch/hydra/tree/master/examples/instantiate)

This example demonstrates the use of Structured Configs to instantiated objects.

Expand Down

0 comments on commit e4ac92b

Please sign in to comment.