I have a class, say, MyClass . I want to make a decorator for a method of this class (and some others). In the decorator, I would like to have a link to an object of this class.

Python 2 had a great inspect.getargspec function, which is now (in Pyton 3 ) deprecated .

Having stuck in the documentation, I found only a way to find out whether the self argument is in a function or not.

Here is an example of such a search:

 import inspect def get_reference_by_method(f): all_args_of_method = inspect.signature(f).parameters if 'self' in all_args_of_method: print("I've found self!") else: raise Exception('It is not a class method') return None # I don't know how to get a reference on self def super_decorator(f): def wrapper(*args, **kwargs): self = get_reference_by_method(f) return f(*args, **kwargs) return wrapper class MyClass: @super_decorator def decorating_method(self): print('Hello from the decorating method') MyClass().decorating_method() 

Output to console:

 I've found self! Hello from the decorated method 

I can not understand what I need to do to get this self .

  • Not on the topic of the question: checking is so-so, since def foo(bar, baz, self=None) also a completely valid class method, and an object of this class will be passed to bar - andreyman
  • @andreymal yes, I agree. With such a test, I will not go further than my project, in which self everywhere. But are there any more correct alternatives? I can't find anything like that yet. - faoxis

3 answers 3

self is just the first argument to the method:

 import functools def print_self_decorator(method): @functools.wraps(method) def wrapper(self, *args, **kwargs): print(self) return method(self, *args, **kwargs) return wrapper 

Example:

 class C: @print_self_decorator def method(self): print(C.method.__name__) C().method() 

Result:

 <__main__.C object at 0x...> method 
  • this does not answer the question: find out if the self argument is in the function? e.g. @staticmethod - vadim vaduxa
  • @vadimvaduxa: because there was no such question — look at the title (“trying to determine if there is self in the function” was an unsuccessful attempt to solve in the question). Obviously, the decorator for instance methods is intended. There is no self in \ @staticmethod, there is nothing to look for. - jfs
 from inspect import getmembers, ismethod def super_decorator(f): def wrapper(*args, **kwargs): if args: method = getmembers(args[0], ismethod) print('\n', method or type(f)) if method: self = args[0] return f(*args, **kwargs) return wrapper class MyClass: @super_decorator def decorating_method(self): print('Hello from the decorating method') @super_decorator def decorating_method(self): print('Hello from the decorating method') MyClass().decorating_method() decorating_method(2) 

out:

  [('decorating_method', <bound method MyClass.wrapper of <__main__.MyClass object at 0x02999970>>)] Hello from the decorating method <class 'function'> Hello from the decorating method 
  • But I need to pull out the link to the class object, and not to the method of this object. - faoxis
  • Obviously this is args [0] - vadim vaduxa

You can try this option. Will not work in the event that the function name will coincide with one of the methods in the first argument.

 def super_decorator(f): def wrapper(*args, **kwargs): if args and hasattr(args[0].__class__, f.__name__): print("method") else: print("function") return f(*args, **kwargs) return wrapper class MyClass: @super_decorator def decorating_method(self): print('Hello from the decorating method') @super_decorator def test(value): print("From function", value) MyClass().decorating_method() test([1, 2, 3, 4]) 
  • one
    Can be shortened to if args and hasattr(args[0].__class__, f.__name__) - andreymal
  • Yes, true remark. - Avernial