access __doc__ from within function without reference to function name

Discussion in 'Python' started by SanPy, Oct 2, 2007.

  1. SanPy

    SanPy Guest

    The subject of this message might be a little cryptic, so here's an
    example of what I mean:

    def foo():
    """doc string of foo"""
    print foo.__doc__

    >>> foo()

    doc string of foo

    What I want to know is whether it is possible to call __doc__ against
    some builtin method, like __func__ or something like that. So calling
    __doc__ without the functions name, something like this:

    def foo():
    """doc string of foo"""
    print __func__.__doc__ # pseudo code

    So basically, my question is: is there a way to access a function from
    within itself without using its name?

    Regards, Sander.
     
    SanPy, Oct 2, 2007
    #1
    1. Advertising

  2. SanPy

    Duncan Booth Guest

    SanPy <> wrote:

    > So basically, my question is: is there a way to access a function from
    > within itself without using its name?
    >

    Not really, no. Python is executing a code block, it has no idea which
    function referenced that code block.

    You can get the current code object quite easily (inspect.currentframe
    ().f_code), but the reference from function to code is one way: a single
    code object could be used by multiple functions.

    You can get the source code though, so if you are desperate enough you
    could try parsing the source code to extract the docstring:

    print inspect.getsource(inspect.currentframe())

    Use the name of the function, that's the best way.
     
    Duncan Booth, Oct 2, 2007
    #2
    1. Advertising

  3. SanPy

    Tim Chase Guest

    Re: access __doc__ from within function without reference to functionname

    > The subject of this message might be a little cryptic, so here's an
    > example of what I mean:
    >
    > def foo():
    > """doc string of foo"""
    > print foo.__doc__
    >
    >>>> foo()

    > doc string of foo
    >
    > What I want to know is whether it is possible to call __doc__ against
    > some builtin method, like __func__ or something like that. So calling
    > __doc__ without the functions name, something like this:
    >
    > def foo():
    > """doc string of foo"""
    > print __func__.__doc__ # pseudo code
    >
    > So basically, my question is: is there a way to access a function from
    > within itself without using its name?



    Well, I don't know if it's the best way to do it, but the
    following code I just threw together does the trick for me:

    ###########################################################
    "A module docstring"
    import inspect
    def get_doc_string():
    frame = inspect.stack()[1]
    funcname = frame[3]
    try: # for straight functions
    return eval(funcname).__doc__
    except:
    locals = frame[0].f_locals
    try: # for object methods
    return getattr(locals["self"], funcname).__doc__
    except:
    try: # for class and module docstrings
    return locals["__doc__"]
    except:
    print "If you got here, there's something I missed"
    import pdb; pdb.set_trace()
    return funcname

    if __name__ == "__main__":

    def outer_function():
    "A function docstring"
    s = get_doc_string()
    print s
    return s

    class Foo(object):
    "A class docstring"
    zip = get_doc_string()
    def bar(self):
    "A method's docstring"
    s = get_doc_string()
    print s
    return s

    def f1(func):
    "this is f1"
    s = func()
    print s
    return s

    test = outer_function()
    assert test == "A function docstring"
    foo = Foo()
    assert foo.bar() == "A method's docstring"
    print Foo.zip
    assert Foo.zip == "A class docstring"
    module_docstring = get_doc_string()
    print module_docstring
    assert module_docstring == "A module docstring"
    assert f1(get_doc_string) == "this is f1"

    ###########################################################

    I couldn't find a handy way to get the actual
    function-object/class-object/module/method object for the given
    context without the convoluted try/except block. Perhaps someone
    with more knowledge of the inspect module could reudce that do
    something far more simple. There may also be problems if this is
    imported across modules. But this might help point you in the
    right direction.

    -tkc
     
    Tim Chase, Oct 2, 2007
    #3
  4. SanPy

    Duncan Booth Guest

    Tim Chase <> wrote:

    >> So basically, my question is: is there a way to access a function from
    >> within itself without using its name?

    >
    >
    > Well, I don't know if it's the best way to do it, but the
    > following code I just threw together does the trick for me:


    The original request was to do it without using the function's name, but
    you are depending on that name so your code is easy enough to break. e.g.
    change the definition of f1 to:

    def f2(func):
    "this is f1"
    s = func()
    print s
    return s
    f1 = f2
    del f2

    and the output is:

    A function docstring
    A method's docstring
    A class docstring
    A module docstring
    If you got here, there's something I missed
    > c:\temp\docstring.py(18)get_doc_string()

    -> return funcname
    (Pdb)
     
    Duncan Booth, Oct 2, 2007
    #4
  5. SanPy

    Tim Chase Guest

    Re: access __doc__ from within function without reference to functionname

    > The original request was to do it without using the function's
    > name, but you are depending on that name so your code is easy
    > enough to break. e.g. change the definition of f1 to:
    >
    > def f2(func):
    > "this is f1"
    > s = func()
    > print s
    > return s
    > f1 = f2
    > del f2


    Even Python-proper seems to get "confused" by this (though I
    would contend it's correct behavior):


    ===================================
    def f1():
    raise Exception
    f2 = f1
    del(f1)
    f2()
    ===================================


    The traceback references f1() instead of f2. (other printing than
    the calling line of code from the python file itself)


    ===================================
    Traceback (most recent call last):
    File "x.py", line 5, in ?
    f2()
    File "x.py", line 2, in f1
    raise Exception
    Exception
    ===================================

    pdb suffers the same problem:

    ===================================
    def f1():
    import pdb; pdb.set_trace()
    print 'hello'
    f2 = f1
    del(f1)
    f2()
    ===================================


    then, when run, use "where" to ask where Python thinks you are:


    ===================================
    > c:\temp\z.py(3)f1()

    -> print 'hello'
    (Pdb) where
    c:\temp\z.py(7)?()
    -> f2()
    > c:\temp\z.py(3)f1()

    -> print 'hello'
    ===================================

    It thinks we're in f1 as well even though f1 no longer exists.


    My understanding was that the OP wanted a way to refrain from
    hard-coding the function-name into the body of the function,
    rather than to completely avoid the name of the function ever
    being used anywhere.

    Unless there's a mapping that I couldn't find (that would take
    the current frame and map it to the calling
    function/method/module object) the only way to completely avoid
    this (AFAICT) would be to take the location information returned
    by the stack frame, parse the file, and extract the doc-string
    from the resulting line(s).

    It gets hairier when the python is poorly written as one could
    have pessimal cases of "valid" python docstrings that look like

    def f(x): "docstring"; return x*2

    or

    def f(x):
    "docstring"; return x*2

    or common multiline items like

    def f(x):
    """docstring1
    docstring2"""
    pass

    or even worse,

    def f(x):
    """this is a \"""docstring\"""
    with \\\"""and\""" mutliple lines"""
    pass

    def f(x):
    "this is\
    a docstring"
    pass

    The parser also has to accomodate "raw" and "unicode" string
    prefixes, as they're valid too:

    def f(x):
    r"raw!"
    pass

    def f(x):
    u"Unicode"
    pass


    in addition. Okay...in most of these cases, the pathological
    coder should be taken out back and beaten, but it's a non-trivial
    problem :)

    -tkc
     
    Tim Chase, Oct 2, 2007
    #5
  6. SanPy

    Duncan Booth Guest

    Tim Chase <> wrote:

    > The parser also has to accomodate "raw" and "unicode" string
    > prefixes, as they're valid too:
    >
    > def f(x):
    > r"raw!"
    > pass
    >
    > def f(x):
    > u"Unicode"
    > pass
    >
    >
    > in addition. Okay...in most of these cases, the pathological
    > coder should be taken out back and beaten, but it's a non-trivial
    > problem :)


    Fortunately someone already wrote a parser for Python code, so it is pretty
    trivial:

    >>> import compiler
    >>> class Visitor(compiler.visitor.ASTVisitor):

    def visitFunction(self, node):
    print node.doc

    >>> def showdoc(source):

    compiler.walk(compiler.parse(source), Visitor())


    >>> showdoc(r'''def f(x):

    """this is a \"""docstring\"""
    with \\\"""and\""" mutliple lines"""
    pass
    ''')
    this is a """docstring"""
    with \"""and""" mutliple lines
    >>> showdoc(r'''def f(x):

    u"Unicode" " with concatenation"
    pass
    ''')
    Unicode with concatenation
    >>>
     
    Duncan Booth, Oct 2, 2007
    #6
  7. Re: Where to put the import command in the file?

    En Tue, 02 Oct 2007 19:01:27 -0300, wang frank <>
    escribi�:

    > I am writing Python script now. The project will grow bigger in future.
    > I need to import some packages for several functions, such as numpy.
    > Where is the best plalce to put the import numpy command? Is it fine to
    > put on the first line in the file?


    Yes, this is the usual way.

    > Is it better to put it into each function after the def functionname? or
    > they are the same.


    I only place an import inside a function when it's expensive (e.g. loads a
    lot of things) and not always required, or when it's irrelevant to the
    main purpose of the module (e.g. "import traceback" when it's used just to
    handle some special exceptions).

    > Since numpy function will be used in all files, so I have to import it
    > in each files. Does this will increase the memory usuage or there are
    > better way to do it.


    No. Only the first import actually has to load the module; later imports
    quickly return a reference to the already loaded module.

    --
    Gabriel Genellina
     
    Gabriel Genellina, Oct 3, 2007
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Trevor Taylor

    __doc__ of current function?

    Trevor Taylor, Sep 2, 2004, in forum: Python
    Replies:
    3
    Views:
    609
    Sean Ross
    Sep 2, 2004
  2. David Isaac

    property __doc__

    David Isaac, Jul 1, 2006, in forum: Python
    Replies:
    1
    Views:
    352
    Robert Kern
    Jul 1, 2006
  3. Gabriel Genellina

    __doc__ in compiled script

    Gabriel Genellina, Nov 2, 2006, in forum: Python
    Replies:
    5
    Views:
    289
    Peter Otten
    Nov 3, 2006
  4. gtb

    Printing __doc__

    gtb, Mar 21, 2007, in forum: Python
    Replies:
    7
    Views:
    307
    Bart Ogryczak
    Mar 22, 2007
  5. James T. Dennis
    Replies:
    9
    Views:
    333
    Dennis Lee Bieber
    May 11, 2007
Loading...

Share This Page