0

I have a setup that looks as following:

def docstring_formatter(func):
    func.__doc__ = func.__doc__.format(class_name=func.__self__.__class__.__name__) #this does not work
    return func

class A:
    @docstring_formatter
    def my_function(self):
        """I am a function of class {class_name}"""
        print("test")

class B(A):
    pass

docstring = getattr(B.my_function, "__doc__")
>>> AttributeError: 'function' object has no attribute '__self__'

I would like to access the actual class name that the instance of my_function belongs to. Since I am not instantiating the class I when I am using the help() function, the __self__ property is not instantiated yet and I can also not make use of the functools.wraps function. I would like to find a way to also extract the string B or B.my_function when being passed a my_function object that could either belong to A() or B().

dmmpie
  • 365
  • 2
  • 14

1 Answers1

2

Given the code:

class A:
    def my_function(self):
        print("test")

class B(A):
    pass

b = B()

The my_function object has a self binding to the object you took it from, which is a B, so you can do:

>>> b.my_function.__name__
'my_function'
>>> b.my_function.__self__.__class__.__name__
'B'
Samwise
  • 68,105
  • 3
  • 30
  • 44
  • Thank you for your answer. Unfortunately my current setup differs a bit from what I posted, since I am not calling the function directly but rather calling the `help()` function on it to access its docstring, which means that the class is not properly instantiated yet and I can't make the reference to `__self__` on my function. I have updated the question accordingly. – dmmpie Jun 01 '22 at 15:01
  • 1
    Your updated example doesn't work because the argument to `docstring_formatter` is `A.my_function`, not `b.my_function` as in your original question. There is no `B`, and there isn't even an instance of `A`, until after `docstring_formatter` has already returned. I'd suggest writing your own `help` function so that it can inspect `b.my_function` before doing its formatting on `b.my_function.__doc__`. – Samwise Jun 01 '22 at 15:49
  • 1
    I messed around a bit with trying to do this in `__init__` since that does have access to the instance that the method is bound to, but it turns out you can't modify the `__doc__` attribute of a bound method. So yeah, you want to put this logic in `help`, which means you need to override the builtin version. – Samwise Jun 01 '22 at 16:12