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