1

Lets say I have a function like this:

def square(n):
    '''Takes in a number n, returns the square of n'''
    how_can_I_do_this = __doc__

Is there any way I get the __doc__ string without mentioning the function name? That is, how do I print the __doc__ string of a function inside the function without specifying the name of the function?

Jacob Lee
  • 4,405
  • 2
  • 16
  • 37
Allan Xu
  • 7,998
  • 11
  • 51
  • 122
  • Any particular reason you wouldn't just go through the function name? – user2357112 May 13 '21 at 02:55
  • because I am learning Python. I am a C# developer and in C# we have an elegant name to get a reflection reference. I like to know how it works in Python. – Allan Xu May 13 '21 at 02:59
  • In addition, I am simplifying a more complex scenario. If I get what I need, I can sole another problem where I need to get the doc string of whoever calling me. It simplifies my logging scenarios. – Allan Xu May 13 '21 at 03:01
  • Stuff like what you're asking for [has been proposed](https://www.python.org/dev/peps/pep-3130/), but edge cases were unclear and no one had a compelling use case. – user2357112 May 13 '21 at 03:04
  • Couldn't you use the method suggested [here](https://stackoverflow.com/questions/39078467/python-how-to-get-the-calling-function-not-just-its-name), then reference the `__doc__` attribute of the returned function? – Jacob Lee May 13 '21 at 03:26
  • @JacobLee, Isn't the solution below shorter and more concise? – Allan Xu May 13 '21 at 03:28

3 Answers3

2

reference:

How to print Docstring of python function from inside the function itself?

code:

import inspect

def square(n):
    '''Takes in a number n, returns the square of n'''
    print(inspect.getdoc(globals()[inspect.getframeinfo(inspect.currentframe()).function]))

square(0)

result:

Takes in a number n, returns the square of n
leaf_yakitori
  • 2,232
  • 1
  • 9
  • 21
1

You can make use of built-in library inspect to get the required info. You can use it to getinfo about the caller also (which you mention in your comment). Please see example below:

import inspect

def sq(num):
    '''returns square of number'''
    info = inspect.stack()
    current = globals()[info[0].function]
    caller = globals()[info[1].function]
    print(current.__doc__)
    print(caller.__doc__)
    return num*num

def call_sq(num):
    '''calls sq with num'''
    ans = sq(num)
    return ans

def print_sq(num):
    '''calls call_sq to get ans and prints it'''
    ans = call_sq(num)
    print(f'Square of {num} is {ans}')

print_sq(5)

Running this gives me:

returns square of number
calls sq with num
Square of 5 is 25

lllrnr101
  • 2,288
  • 2
  • 4
  • 15
1

You could create a function decorator, similar to below:

def get_docstring(func):
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs), func.__doc__
    return wrapper

@get_docstring
def square(n):
    """
    Returns the square of n
    """
    return n ** 2

When calling the square() function:

>>> square(5)
(25, '\n\tReturns the square of n\n\t')
>>> res, doc = square(5)
>>> res
25
>>> doc
'\n\tReturns the square of n\n\t'
>>> print(doc)

    Returns the square of n
    

For print the docstring inside the function, just pass func.__doc__ before passing **kwargs inside wrapper():

def get_docstring(func):
    def wrapper(*args, **kwargs):
        return func(*args, func.__doc__, **kwargs) 
    return wrapper

@get_docstring
def square(n, doc):
    """
    Returns the square of n
    """
    print(doc)
    return n ** 2

When calling the square() function:

>>> square(5)

    Returns the square of n
    
25
Jacob Lee
  • 4,405
  • 2
  • 16
  • 37
  • 1
    with so many good smart answers, i don't know which one to mark – Allan Xu May 13 '21 at 15:28
  • 1
    @AllanXu There's no pressure to mark specific questions as the accepted answer. Remember: _The accepted answer signifies which answer worked best for OP_. So, whichever one _you_ ended up implementing is the accepted answer, and that should be respected. :) – Jacob Lee May 13 '21 at 15:30