Search code examples
pythondecoratorpython-decoratorscallable

How can I decorate a "callable" class with a class decorator?


I'm looking to decorate a "callable" class (one that has the __call__ method defined), so that I can start a background service before __init__ is called and manipulate the arguments passed before it itself is called to include the details of the service that's been started.

So, for example:

@init_service # starts service on port 5432
class Foo(object):
  def __init__(self, port=9876):
    # init here. 'port' should now be `5432` instead of the original `9876`

  def __call__(self):
    # calls the background service here, using port `5432`

func = Foo(port=9876)
...
result = func()

The class init_service would have a class attribute with the port number, so that later on the service can be shut-down.


Solution

  • You are trying to patch the __init__ method; the fact that there is a __call__ method as well makes no odds here.

    You'd normally decorate the __init__ method instead, using a regular (function) decorator; if you have to use a class decorator, then use one that subclasses the decorated class:

    def init_service(cls):
        class InitService(cls):
            def __init__(self, port='ignored'):
                super(InitService).__init__(5432)
    
        return InitService