Search code examples
pythonabstraction

Python class decorator, cannot use constructor


So I have the following decorator code

class Factory:

    def __init__(self, cls):
        self.cls = cls

    def __instancecheck__(self, inst):
        return isinstance(inst, self.cls)

    def Produce(self):
        return self.cls()

And the following class code

@Factory
class Foo:

    def __init__(self, arg):
        self.arg = arg

    def method(self): pass

Which works great. Allows me to do stuff like

Foo.Produce().method()

Instead of

instance = Foo()
instance.method()

But now I cant use the class constructor normally

Foo(arg)

Gives the exception 'Factory object is not callable'. My question is the following: How can I make a decorator that allows me to instantiate the decorated class using its constructor, but also allows me to use a function in the decorator?

Alternative ways I'd rather not use:

  1. Skip the constructor. Always use <Class>.Produce() (and use *args/**kwargs to make it abstract/reusable.
  2. Use setters in all the classes, and make them return self so they can be chained.
  3. Make a class containing the produce method and extend this class.

Solution

  • The exception is telling you all you need to know, just add a __call__ method:

    class Factory:
        # ...
    
        def __call__(self, *args, **kwargs):
            return self.cls(*args, **kwargs)