decorators only when __debug__ == True

MRAB python at mrabarnett.plus.com
Wed Mar 31 17:27:05 EDT 2010


LX wrote:
> On Mar 30, 2:41 pm, MRAB <pyt... at mrabarnett.plus.com> wrote:
>> LX wrote:
>>> On Mar 29, 6:34 pm, MRAB <pyt... at mrabarnett.plus.com> wrote:
>>>> LX wrote:
>>>>> Hi all, I have a question about decorators. I would like to use them
>>>>> for argument checking, and pre/post conditions. However, I don't want
>>>>> the additional overhead when I run in non-debug mode. I could do
>>>>> something like this, using a simple trace example.
>>>>> @decorator
>>>>> def pass_decorator(f, *args, **kw): # what about the slow-down that
>>>>> incurs when using pass_decorator?
>>>>>     return f(*args, **kw)
>>>>> @decorator
>>>>> def trace_decorator(f, *args, **kw):
>>>>>     print "calling %s with args %s, %s" % (f.func_name, args, kw)
>>>>>     return f(*args, **kw)
>>>>> trace_enable_flag = False #__debug__
>>>>> trace = trace_decorator if trace_enable_flag else pass_decorator
>>>>> Trouble is, there is still an additional encapsulating function call.
>>>>> Is there any way to eliminate the extra function call altogether?
>>>>> Thanks in advance!
>>>> I think you have misunderstood certain details about decorators.
>>>> This code with adecorator:
>>>>      @decorator
>>>>      def hello():
>>>>          print "hello world"
>>>> basically does this:
>>>>      def hello():
>>>>          print "hello world"
>>>>      hello =decorator(hello)
>>>> so your non-decoratorjust needs to return the function it was passed:
>>>>      def pass_decorator(func):
>>>>          return func
>>>> and your tracedecoratorwould be something like this:
>>>>      def trace_decorator(func):
>>>>          def show(*args, **kwargs):
>>>>              print "calling %s with args %s, %s" % (func.func_name,
>>>> args, kwargs)
>>>>              result = func(*args, **kwargs)
>>>>              print "returning %s from %s" % (result, func.func_name)
>>>>              return result
>>>>          return show
>>> Sure, but during runtime, pass_decorator will still be called, even
>>> though it doesn't do anything. I am wondering if I can disable this
>>> additional function call at non-debug runtime. In other words, I want
>>> the calling stack to contain nodecoratorat all, not even
>>> pass_decorator.
>>> I should mention that, in my code, the symbol "decorator" is imported
>>> from Michele Simionato'sdecorator.py file.
>> pass_decorator will be called when the decorated function is _defined_,
>> but not when the decorated function is _called_.
> 
> Why is it then that during runtime, with a breakpoint in some
> arbitrary main() in main.py, I get something similar to the following
> call stack:
> 
> main.py, line xxx, in <module>
>  main()
> 
> <string>, line 2, in main
> 
> decorator.py, line 261, in pass_decorator
>  return f(*args, **kw)
> 
> main.py, line yyy, in main()
>  * breakpoint line here *
> 
> It looks to me the call stack still includes the additional level of
> the decorator... what am I missing? Thank you for your time.

Are you still defining your decorators in the same way as in your
original post?

A decorator shouldn't call the function it's decorating.

My version of pass_decorator just returns the function it's decorating,
not call it, and my version of trace_decorator returns a locally-defined
function which will call the decorated function.



More information about the Python-list mailing list