registrable
allennlp.common.registrable
allennlp.common.registrable.Registrable
is a "mixin" for endowing
any base class with a named registry for its subclasses and a decorator
for registering them.
T#
T = TypeVar("T", bound="Registrable")
Registrable#
class Registrable(FromParams)
Any class that inherits from Registrable
gains access to a named registry for its
subclasses. To register them, just decorate them with the classmethod
@BaseClass.register(name)
.
After which you can call BaseClass.list_available()
to get the keys for the
registered subclasses, and BaseClass.by_name(name)
to get the corresponding subclass.
Note that the registry stores the subclasses themselves; not class instances.
In most cases you would then call from_params(params)
on the returned subclass.
You can specify a default by setting BaseClass.default_implementation
.
If it is set, it will be the first element of list_available()
.
Note that if you use this class to implement a new Registrable
abstract class,
you must ensure that all subclasses of the abstract class are loaded when the module is
loaded, because the subclasses register themselves in their respective files. You can
achieve this by having the abstract class and all subclasses in the init.py of the
module in which they reside (as this causes any import of either the abstract class or
a subclass to load all other subclasses and the abstract class).
default_implementation#
class Registrable(FromParams):
| ...
| default_implementation: Optional[str] = None
register#
class Registrable(FromParams):
| ...
| @classmethod
| def register(
| cls: Type[T],
| name: str,
| constructor: str = None,
| exist_ok: bool = False
| )
Register a class under a particular name.
Parameters
- name :
str
The name to register the class under. - constructor :
str
, optional (default =None
)
The name of the method to use on the class to construct the object. If this is given, we will use this method (which must be a@classmethod
) instead of the default constructor. - exist_ok :
bool
, optional (default =False
)
If True, overwrites any existing models registered undername
. Else, throws an error if a model is already registered undername
.
Examples
To use this class, you would typically have a base class that inherits from Registrable
:
class Vocabulary(Registrable):
...
Then, if you want to register a subclass, you decorate it like this:
@Vocabulary.register("my-vocabulary")
class MyVocabulary(Vocabulary):
def __init__(self, param1: int, param2: str):
...
Registering a class like this will let you instantiate a class from a config file, where you
give "type": "my-vocabulary"
, and keys corresponding to the parameters of the __init__
method (note that for this to work, those parameters must have type annotations).
If you want to have the instantiation from a config file call a method other than the
constructor, either because you have several different construction paths that could be
taken for the same object (as we do in Vocabulary
) or because you have logic you want to
happen before you get to the constructor (as we do in Embedding
), you can register a
specific @classmethod
as the constructor to use, like this:
@Vocabulary.register("my-vocabulary-from-instances", constructor="from_instances")
@Vocabulary.register("my-vocabulary-from-files", constructor="from_files")
class MyVocabulary(Vocabulary):
def __init__(self, some_params):
...
@classmethod
def from_instances(cls, some_other_params) -> MyVocabulary:
... # construct some_params from instances
return cls(some_params)
@classmethod
def from_files(cls, still_other_params) -> MyVocabulary:
... # construct some_params from files
return cls(some_params)
by_name#
class Registrable(FromParams):
| ...
| @classmethod
| def by_name(cls: Type[T], name: str) -> Callable[..., T]
Returns a callable function that constructs an argument of the registered class. Because
you can register particular functions as constructors for specific names, this isn't
necessarily the __init__
method of some class.
resolve_class_name#
class Registrable(FromParams):
| ...
| @classmethod
| def resolve_class_name(
| cls: Type[T],
| name: str
| ) -> Tuple[Type[T], Optional[str]]
Returns the subclass that corresponds to the given name
, along with the name of the
method that was registered as a constructor for that name
, if any.
This method also allows name
to be a fully-specified module name, instead of a name that
was already added to the Registry
. In that case, you cannot use a separate function as
a constructor (as you need to call cls.register()
in order to tell us what separate
function to use).
list_available#
class Registrable(FromParams):
| ...
| @classmethod
| def list_available(cls) -> List[str]
List default first if it exists