Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #3507

Re: How to create a (transparent) decorator with status information?

Path csiph.com!x330-a1.tempe.blueboxinc.net!usenet.pasdenom.info!aioe.org!feeder.news-service.com!newsfeed.xs4all.nl!newsfeed5.news.xs4all.nl!xs4all!post.news.xs4all.nl!not-for-mail
Return-Path <wwitzel3@gmail.com>
X-Original-To python-list@python.org
Delivered-To python-list@mail.python.org
X-Spam-Status OK 0.011
X-Spam-Evidence '*H*': 0.98; '*S*': 0.00; 'wrapper': 0.07; 'decorator': 0.09; 'email name:': 0.09; '>>>': 0.12; 'def': 0.13; 'skip:f 30': 0.14; '**kwargs)': 0.16; '**kwargs):': 0.16; '*args,': 0.16; '*p,': 0.16; 'approach,': 0.16; 'emits': 0.16; 'file).': 0.16; 'obj,': 0.16; 'subject:create': 0.16; 'test()': 0.16; 'test():': 0.16; 'object,': 0.19; 'cc:no real name:2**0': 0.20; 'cc:2**0': 0.20; 'header:In-Reply-To:1': 0.22; 'cc:addr :python-list': 0.22; 'e.g.': 0.22; 'somehow': 0.23; '(e.g.': 0.26; 'object': 0.27; 'pass': 0.27; 'function': 0.27; 'shared': 0.29; 'received:209.85.161': 0.29; 'error': 0.29; 'problem': 0.29; 'subject:?': 0.29; 'class': 0.29; 'cc:addr:python.org': 0.31; "can't": 0.31; 'idea': 0.32; 'thinking': 0.33; 'using': 0.34; 'header:User-Agent:1': 0.35; 'function.': 0.35; 'instances': 0.35; 'maintained': 0.35; 'try:': 0.35; 'case,': 0.36; 'problems': 0.37; 'data': 0.37; 'however': 0.37; 'self': 0.37; 'received:209.85': 0.37; 'either': 0.37; 'subject:with': 0.37; 'logging': 0.38; 'received:google.com': 0.38; 'user': 0.38; 'but': 0.38; 'completely': 0.38; 'unless': 0.38; 'help': 0.39; 'could': 0.39; 'subject: (': 0.39; 'received:209': 0.39; 'except': 0.39; 'might': 0.40; 'give': 0.61; 'transparent': 0.65; 'yourself': 0.66; 'needing': 0.68; 'to:addr:googlegroups.com': 0.69; 'reply-to:no real name:2**0': 0.72; 'header:Reply-To:1': 0.72; '(let': 0.84; 'reply-to:addr:googlegroups.com': 0.93
Newsgroups comp.lang.python
Date Mon, 18 Apr 2011 16:04:15 -0700 (PDT)
In-Reply-To <mailman.510.1303130820.9059.python-list@python.org>
Complaints-To groups-abuse@google.com
Injection-Info glegroupsg2000goo.googlegroups.com; posting-host=24.136.39.61; posting-account=WYXHHQoAAACf1K2fErnkg7Hz-zChJNuw
User-Agent G2/1.0
MIME-Version 1.0
Subject Re: How to create a (transparent) decorator with status information?
From Wayne Witzel III <wwitzel3@gmail.com>
To comp.lang.python@googlegroups.com
Content-Type text/plain; charset=ISO-8859-1
Cc python-list@python.org
X-BeenThere python-list@python.org
X-Mailman-Version 2.1.12
Precedence list
Reply-To comp.lang.python@googlegroups.com
List-Id General discussion list for the Python programming language <python-list.python.org>
List-Unsubscribe <http://mail.python.org/mailman/options/python-list>, <mailto:python-list-request@python.org?subject=unsubscribe>
List-Archive <http://mail.python.org/pipermail/python-list>
List-Post <mailto:python-list@python.org>
List-Help <mailto:python-list-request@python.org?subject=help>
List-Subscribe <http://mail.python.org/mailman/listinfo/python-list>, <mailto:python-list-request@python.org?subject=subscribe>
Message-ID <mailman.526.1303167857.9059.python-list@python.org> (permalink)
Lines 67
NNTP-Posting-Host 82.94.164.166
X-Trace 1303167858 news.xs4all.nl 81473 [::ffff:82.94.164.166]:51681
X-Complaints-To abuse@xs4all.nl
Xref x330-a1.tempe.blueboxinc.net comp.lang.python:3507

Show key headers only | View raw


> 
> Thinking object-orientedly, my first idea was to use an object as a
> decorator:
> 
> class CallCounter:
>   def __init__(self, decorated):
>     self.__function = decorated
>     self.__numCalls = 0
> 
>   def __call__(self, *args, **kwargs):
>     self.__numCalls += 1
>     return self.__function(*args, **kwargs)
> 
>   # To support decorating member functions
>   def __get__(self, obj, objType):
>     return functools.partial(self.__call__, obj)
> 
> This approach however has three problems (let "decorated" be a function
> decorated by either call_counts or CallCounter):
> 
> * The object is not transparent to the user like call_counts is. E.g.
>   help(decorated) will return CallCounter's help and decorated.func_name
>   will result in an error although decorated is a function.
> * The maintained status is not shared among multiple instances of the
>   decorator. This is unproblematic in this case, but might be a problem
>   in others (e.g. logging to a file).
> * I can't get the information from the decorator, so unless CallCounter
>   emits the information on its own somehow (e.g. by using print), the
>   decorator is completely pointless.
> 

Going with the object approach, you could use Borg to give yourself the state between instances you mentioned. And since you are using an object, you'll have access to the data without needing to return it from the decorator.

class StatefulDecorators(object):
    _state = {}
    def __new__(cls, *p, **k):
        self = object.__new__(cls, *p, **k)
        self.__dict__ = cls._state
        return self
            
    def count_calls(self, function):
        @functools.wraps(function)
        def wrapper(*args, **kwargs):
            try:
                self.calls += 1
            except AttributeError:
                self.calls = 1
            return function(*args, **kwargs)
        return wrapper

>>> sd = StatefulDecorators()
>>> @sd.count_calls
... def test():
...     pass
>>> test()
>>> sd.calls
1
>>> sd1 = StatefulDecorators()
>>> @sd1.count_calls
... def test2():
...     pass
>>> test2()
>>> sd1.calls
2
>>> sd.calls
2

Back to comp.lang.python | Previous | Next | Find similar | Unroll thread


Thread

Re: How to create a (transparent) decorator with status information? Wayne Witzel III <wwitzel3@gmail.com> - 2011-04-18 16:04 -0700

csiph-web