0

I have added my decorator to instance methods of the class:

def method_decorator(func):
    def wrap(self, *args, **kwargs):
        print("Start to perform " + func.__name__)
        try:
            func(self, *args, **kwargs)
        finally:
            print("Finish to perform " + func.__name__ + "\n")

    # make func calling without decorator
    wrap.no_decorator = func
    return wrap


class Simulator:
    def __init__(self):
        self.busy = False

    @method_decorator
    def get_smth(self, text):
        print('test')
        ...


Simulator().get_smth('text') -> works

But how can I call get_smth without decorator involving?

You can see in the code that I tried to attach origin func to result from decorator method (as suggested at one of the SO answers), but it doesn't work.

Simulator().get_smth.no_decorator('text') -> requires parameter for `get_smth`

Is there a way to achieve this with Python 3? Also, I would like to call the undecorated function from other instance methods of this class

  • Maybe `Import Simulator as sm` and then `sm.get_smth("")` ? – Ivan Jan 22 '20 at 16:42
  • This isn't even about decorators. You are accessing an unbound function. Your `get_smth()` function definition expects two arguments, so you need to *pass those in explicitly*. Or bind the method. – Martijn Pieters Jan 22 '20 at 16:46
  • 1
    `Simulator().get_smth` is a bound method (it is a special object with `__func__` and `__self__` attributes, calling it triggers `__func__(__self__, ... other args ...)`. The `no_decorator` attribute is just a function, not a bound method. You need to pass in the instance manually, or explicitly bind the function to the instance. – Martijn Pieters Jan 22 '20 at 16:49
  • E.g. `instance = Simulator()`, then `instance.get_smth.no_decorator(instance, 'text')`. See the duplicates. – Martijn Pieters Jan 22 '20 at 16:49
  • @MartijnPieters have a look at the answer I copy solution from: https://stackoverflow.com/a/37568895/3666523. As you can see there is no parameters in the first function – Gleb Mikulko Jan 22 '20 at 16:50
  • Next, you want to start using [`@functools.wraps()`](https://docs.python.org/3/library/functools.html#functools.wraps), at which point you automatically will have a `__wrapper__` attribute on your decorated functions. No need to set `no_decorator` manually then. – Martijn Pieters Jan 22 '20 at 16:50
  • @MartijnPieters ok, I wasn't clear. I want to call the function with no decorator from another instance method of `Simulator` – Gleb Mikulko Jan 22 '20 at 16:51
  • @GlebMikulko: nowhere in that answer is the function used in a class. Because you put `get_smth` *in a class* then access the name *on an instance of the class*, `self` is passed into methods. But `no_decorator` is not an attribute on an instance, it is an attribute on a method object. So it is not bound, `self` is not passed in automatically. – Martijn Pieters Jan 22 '20 at 16:51
  • 1
    @GlebMikulko: then use `self.get_smth.no_decorator(self, ...)`. Pass in a value for the first argument, the `self` argument, manually. – Martijn Pieters Jan 22 '20 at 16:52
  • @GlebMikulko: or create your own method object: `undecorated = self.get_smth.no_decorator.__get__(self)`, then you can use `undecorated('text')`. It's `function.__get__(instance)` that creates the method object, and Python does this for you automatically when you use `instance.name_of_function_on_class`. – Martijn Pieters Jan 22 '20 at 16:53
  • @MartijnPieters, looks like `self` as a first argument solved my issue – Gleb Mikulko Jan 22 '20 at 16:57

0 Answers0