__func__ missing!?

Sometimes it might be an indication for a flaw in your design, but to me the people programming Python seem to be mature enough to figure that one out. And every other language has a kind of __func__ constant. But why does Python not? Is it that I am really picky? Actually I just wanted to print out the __doc__ string of my function to show it as the instruction to the user on an interactive shell skript. But since the __doc__ refers to the modules doc-string I thought I would get access to my function’s doc-string by some kind of __func__ constant. So I asked in #python, but as there is written in a Python Cookbook’s recipe too, there is no such constant.
I only wanted to do:


    def get_input():
        '''Here are the instructions of what input I expect
        and of what the function does, two things in one, I am just lazy!
        '''
        print __func__.__doc__
        inp = raw_input('Please input here: ')
        # Prepare input data ...
        return inp

I may still have to get my head around to better understand Python …

14 Comments »

  1. Doug Winter said,

    October 20, 2005 at 10:50 am

    You can access it through the name of the function though: get_input.__doc__ will work?

  2. Wolfram said,

    October 20, 2005 at 10:57 am

    Thanks. I didnt want to do that, because I am at an very early stage, where I don’t know if I might change the entire design and also the function names, therefore I wanted to use a constant.
    Currently I am doing
    def get_input():
    ….doc = “”" …. “”"
    ….print doc
    Gives me kind of the feeling to have an incline doc :-)

  3. Tim Jarman said,

    October 20, 2005 at 12:38 pm

    You could define a function like this:


    import inspect

    def get_name():
    "Returns the name of the calling function."
    frame = inspect.currentframe()
    return frame.f_back.f_code.co_name

    Use it like so:


    def test():
    print "My name is %s" % get_name()

    test()

    It's not lovely, but it works...

  4. Anonymous said,

    October 20, 2005 at 12:50 pm

    how about

    class autocomment( fun ):
    def __init__( fun ): self.fun = fun
    def __call__( self, *args, **kwargs ):
    print fun.__doc__
    return fun( *args, **kwargs )

    @autocomment
    def get_name():
    ”’Here are the instructions of what input I expect
    and of what the function does, two things in one, I am just lazy!
    ”’
    inp = raw_input(’Please input here: ‘)
    return inp

    ?

  5. Wolfram said,

    October 20, 2005 at 1:17 pm

    this @autocomment is pretty lovely … I might consider that.

    But still I don’t understand why Python has no __func__ :-)

  6. Florian said,

    October 20, 2005 at 2:01 pm

    me= guy with autocomment

    Neither do I understand it. But I’d like to ask a question.

    if __func__ refers to the function you’re in (as in def foo(): __func__ == foo)

    what does __func__ in a class method refer to,

    class bar:
    def foo( self ): __func__ == bar.foo or __func__ == self.foo ?

    and what is it in a generator
    def foo(): yield __func__ == foo or __func__ == foo()?

  7. Wolfram said,

    October 20, 2005 at 2:10 pm

    Well how it could work in Python is probably something smarter people can answer, and well thought-through it might be different to the hacky PHP-solution :-)

  8. Bob Ippolito said,

    October 20, 2005 at 10:29 pm

    The get_name() function above is basically identical to the hacky PHP solution: it returns the name of the current function.

  9. Simon said,

    October 20, 2005 at 11:24 pm

    A bit off-topic perhaps, but are there any benefits to having decorator implemented as a class?

    As for __func__ for a method, I think it should return . to allow method unbinding (via staticmethod() decorator).

  10. Simon said,

    October 20, 2005 at 11:26 pm

    Ups, I shouldn’t have used < so carelessly. The last sentence should read:

    As for __func__ for a method, I think it should return &;ltclass_name>.<method_name> to allow method unbinding (via staticmethod() decorator).

    Sorry for the mess.

  11. Florian said,

    October 21, 2005 at 8:55 am

    There is an advantage to a decorator beeing a class rather then nested functions.

    It has to do with name binding, not entirely unlike the issue of lambdas in loops if I remember correctly.

  12. pterk said,

    October 22, 2005 at 1:01 pm

    It’s not ‘__func__’ but it’s a bit more dynamic than the earlier example using inspect. Another candidate might be getattr but I never know how the use getattr outside classes.

    import inspect

    def getname():
    “”"Here are the instructions of what input I expect
    and of what the function does, two things in one, I am just lazy!
    “”"
    f = inspect.currentframe().f_code.co_name
    print globals()[f].__doc__
    inp = raw_input(’Please input here: ‘)
    # Prepare input data …
    return inp

  13. dbrodie said,

    October 23, 2005 at 10:21 pm

    The problem with a __func__ variable is the same problem with the inspect.currentframe solution that Florian and Simon said were discussing.

    If __func__ will equal classname.funcname then it will not really be the function inside of which you are running. Example (using squigglies so tabbing dosn’ get messed up):
    class a
    {
    def h(): pass
    print id(h)
    }
    print id(h)

    as you will see you get different values. (Look at type(a.h))

    And if you do the function inside which you are really running then it is not the actual function that is getting called.

    These same problems will exsist with decorators if they return new functions. So should __func__ refer to the new function or to the original one?

    All of these can cause some very subtle bugs depending on how you are going to use it. Ok, if you use __doc__ then it works great, but how about if you are trying to access func_* and some decorator is actually implemented as a class (like instancemethod).

    Anyway, it might SEEM simple but depending on what you are doing, this can lead to very subtle bugs.

  14. Chris Prinos said,

    November 23, 2006 at 6:19 pm

    You don’t need a magic method, just use the function name itself:

    def foo():
    ‘this is doc for foo’
    print foo.__doc__

RSS feed for comments on this post · TrackBack URL

Leave a Comment