Function and method debugging decorator - Part 2
You can improve the following:


            if getargspec(function).args[0] != "self":
                print(self.__format_debug_string(function, *args, **kwargs))
            else:
                print(self.__format_debug_string(function, *args, **kwargs))
                print("[debug] Parent attributes: {}".format(pformat(args[0].__dict__)))



If the code is executed no matter the statement, and it always goes first, move it above the condition: (and don't forget to reverse the condition)

            print(self.__format_debug_string(function, *args, **kwargs))
            if getargspec(function).args[0] == "self":
                print("[debug] Parent attributes: {}".format(pformat(args[0].__dict__)))


As for this:


    debug_string = ""
    debug_string += "[debug] {}\n".format(pformat(function))
    debug_string += "[debug] Passed args: {}\n".format(pformat(args))
    debug_string += "[debug] Passed kwargs: {}\n".format(pformat(kwargs))
    debug_string += "[debug] Locals: {}".format(pformat(function.__code__.co_varnames))
    return debug_string



You can remove the = "" entirely:

    debug_string =  "[debug] {}\n".format(pformat(function))
    debug_string += "[debug] Passed args: {}\n".format(pformat(args))
    debug_string += "[debug] Passed kwargs: {}\n".format(pformat(kwargs))
    return debug_string + "[debug] Locals: {}".format(pformat(function.__code__.co_varnames))


It may not look as visually stimulating, but, it's not as redundant.


  Is it a good idea to create an empty string, and then add to, and re-assign it to build an output string?


If you were directly printing these then it would be a bad idea, but in this case, not really. However, I suppose you could move them to an object, or an array and return the result of a join function.

You could even return it as an array, and print each [debug] result. Which would remove the need for the \ns at the end, and DRY up the [debug] at the beginning of the strings (put it in the loop, not altogether)



You've got a few too long lines, by PEP8 standard:


debug -- Whether or not you want to output debug info. Generally, a global DEBUG variable is passed in here.
debug_string += "[debug] Locals: {}".format(pformat(function.__code__.co_varnames))
print(self.__format_debug_string(function, *args, **kwargs))
print("[debug] Parent attributes: {}".format(pformat(args[0].__dict__)))





As for your documentation:


function, it will print out the arguments of

Keyword arguments:



I'm a bit confused by that, grammatically.

__call__ is a more complex function (in my mind, at least) than __format_debug_string, but it has no documentation.




  Is this Python 3, and Python 2.7 compatible?


It ran fine when I tested it in Python 2.7.9 and 3.1.1