0

I have a class, and I would prefer that people call a factory method in order to create instance of the class instead of instantiating the class directly.

One of a few different reasons to use a factory method is so that we can use functools.wrap to wrap un-decorated callable.

import inspect 

class Decorator:
    def __init__(self, kallable):
        self._kallable = kallable
        
    @classmethod
    def make_decorator(kls, kallable):
        wrapped_kallable = kls(kallable)
        return functools.wrap(wrapped_kallable, kallable)
        
    def __call__(self, *args, **kwargs):
        func_name = self._kallable.__name__ 
        func_name = inspect.currentframe().f_code.co_name
        
        print("ENTERING FUNCTION ", func_name)
        
        ret_val = self._kallable(*args, **kwargs)
        
        print("LEAVING FUNCTION", self._kallable)
        
        return ret_val

Printing "ENTERING FUNCTION " is kind of a silly thing to do, I wanted to show you a minimal reproducible example of what I am trying to do (create a decorator-class which uses functools.wrap and which is instantiated from a factory method)

Toothpick Anemone
  • 4,290
  • 2
  • 20
  • 42
  • Maybe this is what you're looking for: https://stackoverflow.com/questions/8212053/private-constructor-in-python – Gene Mar 13 '23 at 01:29

1 Answers1

2

You don't need to create a factory method for the purpose of calling functools.wraps on the instance being created. Override the __new__ method instead:

class Decorator:
    def __new__(cls, kallable):
        return functools.wraps(kallable)(super().__new__(cls))

Demo: https://replit.com/@blhsing/MediumpurpleBraveCleaninstall

blhsing
  • 91,368
  • 6
  • 71
  • 106
  • Should `__new__` accept only the class as input, or should we also pass an instance of the class into `__new__`? Do we write `super().__new__(cls, kallable)` or only `super().__new__(cls)`? – Toothpick Anemone Mar 15 '23 at 19:29