1

I am using the stanza NLP library which uses a decorator to register processors. Stanza has a help page for building your own processors here

They use a class decorator @register_processor("processor_name"). The code for register_processor appears pretty simple. It puts the name of the processor in a dict as the key and the class as the value.

It is unclear to me when the decorator, or the function attached to this decorator is called. Is it called just before the class it initialised or at some other point?

I did try Google searching, I found lots on how to use decorators and when function decorators are called but I couldn't find this specific answer on class decorators easily.

jonrsharpe
  • 115,751
  • 26
  • 228
  • 437
RodP
  • 382
  • 2
  • 12
  • 3
    It's called just after the class itself is created, _with_ the class (exactly as a function decorator is called just after the function is created, with the function). – jonrsharpe May 07 '22 at 09:07
  • Ah, I think I was making a false assumption. Init is not a constructor (https://stackoverflow.com/questions/6578487/init-as-a-constructor). Simply importing a class into my module results in its 'creation' and the decorator is called before init. Is that correct? – RodP May 07 '22 at 11:33
  • 1
    It's called when that module is loaded, usually as the result of (first) being imported, yes. That's when the top-level code, including class and function definitions, runs. – jonrsharpe May 07 '22 at 11:35

1 Answers1

3

As @jonrsharpe said, it's called after the class has been built. Here's an example of a similar decorator. (Note how the register_class function actually returns a specific inner function; that's the general pattern for any decorator in Python.)

registry = {}


def register_class(name):
    def decorator(cls):
        registry[name] = cls
        print(f"Registered {name}: {cls}")
        return cls

    return decorator


print("Hello!")


@register_class("foo")
class Bloop:
    pass


print(f"Hi there! We have {registry} in the house.")


@register_class("another")
class Else:
    pass

print(f"Whew, that's a lot of classes! {registry}")

This prints out

Hello!
Registered foo: <class '__main__.Bloop'>
Hi there! We have {'foo': <class '__main__.Bloop'>} in the house.
Registered another: <class '__main__.Else'>
Whew, that's a lot of classes! {'foo': <class '__main__.Bloop'>, 'another': <class '__main__.Else'>}
AKX
  • 152,115
  • 15
  • 115
  • 172
  • 2
    For those looking for references into the official docs: see the descriptions of decorators [for class definitions](https://docs.python.org/3/reference/compound_stmts.html#class-definitions) and [for function definitions](https://docs.python.org/3/reference/compound_stmts.html#function). – Maxpm May 07 '22 at 09:14